提交 f9ad02d9 编写于 作者: L lana

Merge

#
# Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
......@@ -43,8 +43,6 @@ FILES_java = \
com/sun/security/auth/UserPrincipal.java \
com/sun/security/auth/LdapPrincipal.java \
com/sun/security/auth/PolicyFile.java \
com/sun/security/auth/SubjectCodeSource.java \
com/sun/security/auth/PolicyParser.java \
com/sun/security/auth/PrincipalComparator.java \
com/sun/security/auth/callback/TextCallbackHandler.java \
com/sun/security/auth/callback/DialogCallbackHandler.java
......@@ -65,10 +65,6 @@ PROFILE_2_JARS := \
$(if $(PROFILE_2_JRE_JAR_FILES), $(addprefix $(IMAGES_OUTPUTDIR)/lib/, $(PROFILE_2_JRE_JAR_FILES))) \
$(PROFILE_1_JARS)
ifneq ($(ENABLE_JFR), true)
PROFILE_3_JRE_JAR_FILES := $(filter-out jfr.jar, $(PROFILE_3_JRE_JAR_FILES))
endif
PROFILE_3_JARS := \
$(addprefix $(IMAGES_OUTPUTDIR)/lib/, $(PROFILE_3_JRE_JAR_FILES)) \
$(PROFILE_2_JARS)
......@@ -77,6 +73,10 @@ ifdef OPENJDK
FULL_JRE_JAR_FILES := $(filter-out alt-rt.jar, $(FULL_JRE_JAR_FILES))
endif
ifneq ($(ENABLE_JFR), true)
FULL_JRE_JAR_FILES := $(filter-out jfr.jar, $(FULL_JRE_JAR_FILES))
endif
FULL_JRE_JARS := \
$(addprefix $(IMAGES_OUTPUTDIR)/lib/, $(FULL_JRE_JAR_FILES)) \
$(PROFILE_3_JARS)
......
......@@ -87,6 +87,7 @@ class KQueueArrayWrapper {
private int incomingInterruptFD;
static {
IOUtil.load();
initStructSizes();
String datamodel = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("sun.arch.data.model")
......
......@@ -246,9 +246,4 @@ class KQueueSelectorImpl
}
return this;
}
static {
Util.load();
}
}
......@@ -28,6 +28,12 @@
#include "util.h"
#include "SDE.h"
#ifdef __APPLE__
/* use setjmp/longjmp versions that do not save/restore the signal mask */
#define setjmp _setjmp
#define longjmp _longjmp
#endif
/**
* This SourceDebugExtension code does not
* allow concurrent translation - due to caching method.
......
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -59,7 +59,7 @@ import java.io.IOException;
* {@link java.lang.instrument} for a detailed description on how these agents
* are loaded and started). The {@link #loadAgentLibrary loadAgentLibrary} and
* {@link #loadAgentPath loadAgentPath} methods are used to load agents that
* are deployed in a dynamic library and make use of the <a
* are deployed either in a dynamic library or statically linked into the VM and make use of the <a
* href="../../../../../../../../technotes/guides/jvmti/index.html">JVM Tools
* Interface</a>. </p>
*
......@@ -298,25 +298,29 @@ public abstract class VirtualMachine {
* <p> A <a href="../../../../../../../../technotes/guides/jvmti/index.html">JVM
* TI</a> client is called an <i>agent</i>. It is developed in a native language.
* A JVM TI agent is deployed in a platform specific manner but it is typically the
* platform equivalent of a dynamic library. This method causes the given agent
* library to be loaded into the target VM (if not already loaded).
* platform equivalent of a dynamic library. Alternatively, it may be statically linked into the VM.
* This method causes the given agent library to be loaded into the target
* VM (if not already loaded or if not statically linked into the VM).
* It then causes the target VM to invoke the <code>Agent_OnAttach</code> function
* or, for a statically linked agent named 'L', the <code>Agent_OnAttach_L</code> function
* as specified in the
* <a href="../../../../../../../../technotes/guides/jvmti/index.html"> JVM Tools
* Interface</a> specification. Note that the <code>Agent_OnAttach</code>
* Interface</a> specification. Note that the <code>Agent_OnAttach[_L]</code>
* function is invoked even if the agent library was loaded prior to invoking
* this method.
*
* <p> The agent library provided is the name of the agent library. It is interpreted
* in the target virtual machine in an implementation-dependent manner. Typically an
* implementation will expand the library name into an operating system specific file
* name. For example, on UNIX systems, the name <tt>foo</tt> might be expanded to
* <tt>libfoo.so</tt>, and located using the search path specified by the
* <tt>LD_LIBRARY_PATH</tt> environment variable.</p>
* name. For example, on UNIX systems, the name <tt>L</tt> might be expanded to
* <tt>libL.so</tt>, and located using the search path specified by the
* <tt>LD_LIBRARY_PATH</tt> environment variable. If the agent named 'L' is
* statically linked into the VM then the VM must export a function named
* <code>Agent_OnAttach_L</code>.</p>
*
* <p> If the <code>Agent_OnAttach</code> function in the agent library returns
* <p> If the <code>Agent_OnAttach[_L]</code> function in the agent library returns
* an error then an {@link com.sun.tools.attach.AgentInitializationException} is
* thrown. The return value from the <code>Agent_OnAttach</code> can then be
* thrown. The return value from the <code>Agent_OnAttach[_L]</code> can then be
* obtained by invoking the {@link
* com.sun.tools.attach.AgentInitializationException#returnValue() returnValue}
* method on the exception. </p>
......@@ -325,15 +329,16 @@ public abstract class VirtualMachine {
* The name of the agent library.
*
* @param options
* The options to provide to the <code>Agent_OnAttach</code>
* The options to provide to the <code>Agent_OnAttach[_L]</code>
* function (can be <code>null</code>).
*
* @throws AgentLoadException
* If the agent library does not exist, or cannot be loaded for
* another reason.
* If the agent library does not exist, the agent library is not
* statically linked with the VM, or the agent library cannot be
* loaded for another reason.
*
* @throws AgentInitializationException
* If the <code>Agent_OnAttach</code> function returns an error
* If the <code>Agent_OnAttach[_L]</code> function returns an error.
*
* @throws IOException
* If an I/O error occurs
......@@ -359,11 +364,12 @@ public abstract class VirtualMachine {
* The name of the agent library.
*
* @throws AgentLoadException
* If the agent library does not exist, or cannot be loaded for
* another reason.
* If the agent library does not exist, the agent library is not
* statically linked with the VM, or the agent library cannot be
* loaded for another reason.
*
* @throws AgentInitializationException
* If the <code>Agent_OnAttach</code> function returns an error
* If the <code>Agent_OnAttach[_L]</code> function returns an error.
*
* @throws IOException
* If an I/O error occurs
......@@ -383,12 +389,23 @@ public abstract class VirtualMachine {
* <p> A <a href="../../../../../../../../technotes/guides/jvmti/index.html">JVM
* TI</a> client is called an <i>agent</i>. It is developed in a native language.
* A JVM TI agent is deployed in a platform specific manner but it is typically the
* platform equivalent of a dynamic library. This method causes the given agent
* library to be loaded into the target VM (if not already loaded).
* It then causes the target VM to invoke the <code>Agent_OnAttach</code> function
* as specified in the
* platform equivalent of a dynamic library. Alternatively, the native
* library specified by the agentPath parameter may be statically
* linked with the VM. The parsing of the agentPath parameter into
* a statically linked library name is done in a platform
* specific manner in the VM. For example, in UNIX, an agentPath parameter
* of <code>/a/b/libL.so</code> would name a library 'L'.
*
* See the JVM TI Specification for more details.
*
* This method causes the given agent library to be loaded into the target
* VM (if not already loaded or if not statically linked into the VM).
* It then causes the target VM to invoke the <code>Agent_OnAttach</code>
* function or, for a statically linked agent named 'L', the
* <code>Agent_OnAttach_L</code> function as specified in the
* <a href="../../../../../../../../technotes/guides/jvmti/index.html"> JVM Tools
* Interface</a> specification. Note that the <code>Agent_OnAttach</code>
* Interface</a> specification.
* Note that the <code>Agent_OnAttach[_L]</code>
* function is invoked even if the agent library was loaded prior to invoking
* this method.
*
......@@ -396,9 +413,9 @@ public abstract class VirtualMachine {
* agent library. Unlike {@link #loadAgentLibrary loadAgentLibrary}, the library name
* is not expanded in the target virtual machine. </p>
*
* <p> If the <code>Agent_OnAttach</code> function in the agent library returns
* <p> If the <code>Agent_OnAttach[_L]</code> function in the agent library returns
* an error then an {@link com.sun.tools.attach.AgentInitializationException} is
* thrown. The return value from the <code>Agent_OnAttach</code> can then be
* thrown. The return value from the <code>Agent_OnAttach[_L]</code> can then be
* obtained by invoking the {@link
* com.sun.tools.attach.AgentInitializationException#returnValue() returnValue}
* method on the exception. </p>
......@@ -407,15 +424,16 @@ public abstract class VirtualMachine {
* The full path of the agent library.
*
* @param options
* The options to provide to the <code>Agent_OnAttach</code>
* The options to provide to the <code>Agent_OnAttach[_L]</code>
* function (can be <code>null</code>).
*
* @throws AgentLoadException
* If the agent library does not exist, or cannot be loaded for
* another reason.
* If the agent library does not exist, the agent library is not
* statically linked with the VM, or the agent library cannot be
* loaded for another reason.
*
* @throws AgentInitializationException
* If the <code>Agent_OnAttach</code> function returns an error
* If the <code>Agent_OnAttach[_L]</code> function returns an error.
*
* @throws IOException
* If an I/O error occurs
......@@ -441,11 +459,12 @@ public abstract class VirtualMachine {
* The full path to the agent library.
*
* @throws AgentLoadException
* If the agent library does not exist, or cannot be loaded for
* another reason.
* If the agent library does not exist, the agent library is not
* statically linked with the VM, or the agent library cannot be
* loaded for another reason.
*
* @throws AgentInitializationException
* If the <code>Agent_OnAttach</code> function returns an error
* If the <code>Agent_OnAttach[_L]</code> function returns an error.
*
* @throws IOException
* If an I/O error occurs
......
/*
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -50,7 +50,15 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
public
class BufferedInputStream extends FilterInputStream {
private static int defaultBufferSize = 8192;
private static int DEFAULT_BUFFER_SIZE = 8192;
/**
* The maximum size of array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
/**
* The internal buffer array where the data is stored. When necessary,
......@@ -172,7 +180,7 @@ class BufferedInputStream extends FilterInputStream {
* @param in the underlying input stream.
*/
public BufferedInputStream(InputStream in) {
this(in, defaultBufferSize);
this(in, DEFAULT_BUFFER_SIZE);
}
/**
......@@ -215,8 +223,11 @@ class BufferedInputStream extends FilterInputStream {
} else if (buffer.length >= marklimit) {
markpos = -1; /* buffer got too big, invalidate mark */
pos = 0; /* drop buffer contents */
} else if (buffer.length >= MAX_BUFFER_SIZE) {
throw new OutOfMemoryError("Required array size too large");
} else { /* grow buffer */
int nsz = pos * 2;
int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
pos * 2 : MAX_BUFFER_SIZE;
if (nsz > marklimit)
nsz = marklimit;
byte nbuf[] = new byte[nsz];
......
......@@ -1307,7 +1307,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* specified substring, starting at the specified index. The integer
* returned is the smallest value {@code k} for which:
* <blockquote><pre>
* k >= Math.min(fromIndex, str.length()) &&
* k >= Math.min(fromIndex, this.length()) &&
* this.toString().startsWith(str, k)
* </pre></blockquote>
* If no such value of <i>k</i> exists, then -1 is returned.
......@@ -1346,7 +1346,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* specified substring. The integer returned is the largest value <i>k</i>
* such that:
* <blockquote><pre>
* k <= Math.min(fromIndex, str.length()) &&
* k <= Math.min(fromIndex, this.length()) &&
* this.toString().startsWith(str, k)
* </pre></blockquote>
* If no such value of <i>k</i> exists, then -1 is returned.
......
......@@ -3338,8 +3338,16 @@ public final class Class<T> implements java.io.Serializable,
* @since 1.8
*/
public AnnotatedType getAnnotatedSuperclass() {
if (this == Object.class ||
isInterface() ||
isArray() ||
isPrimitive() ||
this == Void.TYPE) {
return null;
}
return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this);
}
}
/**
* Returns an array of AnnotatedType objects that represent the use of types to
......
......@@ -698,11 +698,8 @@ public final class Math {
return 0;
}
private static Random randomNumberGenerator;
private static synchronized Random initRNG() {
Random rnd = randomNumberGenerator;
return (rnd == null) ? (randomNumberGenerator = new Random()) : rnd;
private static final class RandomNumberGeneratorHolder {
static final Random randomNumberGenerator = new Random();
}
/**
......@@ -729,9 +726,7 @@ public final class Math {
* @see Random#nextDouble()
*/
public static double random() {
Random rnd = randomNumberGenerator;
if (rnd == null) rnd = initRNG();
return rnd.nextDouble();
return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
/**
......
......@@ -29,7 +29,6 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.AccessControlException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
......@@ -1033,9 +1032,9 @@ public final class ProcessBuilder
// Can not disclose the fail reason for read-protected files.
try {
security.checkRead(prog);
} catch (AccessControlException ace) {
} catch (SecurityException se) {
exceptionInfo = "";
cause = ace;
cause = se;
}
}
// It's much easier for us to create a high-quality error
......
......@@ -678,11 +678,8 @@ public final class StrictMath {
return Math.round(a);
}
private static Random randomNumberGenerator;
private static synchronized Random initRNG() {
Random rnd = randomNumberGenerator;
return (rnd == null) ? (randomNumberGenerator = new Random()) : rnd;
private static final class RandomNumberGeneratorHolder {
static final Random randomNumberGenerator = new Random();
}
/**
......@@ -709,9 +706,7 @@ public final class StrictMath {
* @see Random#nextDouble()
*/
public static double random() {
Random rnd = randomNumberGenerator;
if (rnd == null) rnd = initRNG();
return rnd.nextDouble();
return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
/**
......
......@@ -2659,28 +2659,32 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
if (ys == 0)
return 1;
int sdiff = this.scale - val.scale;
long sdiff = (long)this.scale - val.scale;
if (sdiff != 0) {
// Avoid matching scales if the (adjusted) exponents differ
int xae = this.precision() - this.scale; // [-1]
int yae = val.precision() - val.scale; // [-1]
long xae = (long)this.precision() - this.scale; // [-1]
long yae = (long)val.precision() - val.scale; // [-1]
if (xae < yae)
return -1;
if (xae > yae)
return 1;
BigInteger rb = null;
if (sdiff < 0) {
if ( (xs == INFLATED ||
(xs = longMultiplyPowerTen(xs, -sdiff)) == INFLATED) &&
// The cases sdiff <= Integer.MIN_VALUE intentionally fall through.
if ( sdiff > Integer.MIN_VALUE &&
(xs == INFLATED ||
(xs = longMultiplyPowerTen(xs, (int)-sdiff)) == INFLATED) &&
ys == INFLATED) {
rb = bigMultiplyPowerTen(-sdiff);
rb = bigMultiplyPowerTen((int)-sdiff);
return rb.compareMagnitude(val.intVal);
}
} else { // sdiff > 0
if ( (ys == INFLATED ||
(ys = longMultiplyPowerTen(ys, sdiff)) == INFLATED) &&
// The cases sdiff > Integer.MAX_VALUE intentionally fall through.
if ( sdiff <= Integer.MAX_VALUE &&
(ys == INFLATED ||
(ys = longMultiplyPowerTen(ys, (int)sdiff)) == INFLATED) &&
xs == INFLATED) {
rb = val.bigMultiplyPowerTen(sdiff);
rb = val.bigMultiplyPowerTen((int)sdiff);
return this.intVal.compareMagnitude(rb);
}
}
......@@ -4545,7 +4549,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
if(cmp > 0) { // satisfy constraint (b)
yscale -= 1; // [that is, divisor *= 10]
int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
if (checkScaleNonZero((long) mcp + yscale) > xscale) {
if (checkScaleNonZero((long) mcp + yscale - xscale) > 0) {
// assert newScale >= xscale
int raise = checkScaleNonZero((long) mcp + yscale - xscale);
long scaledXs;
......@@ -4626,7 +4630,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// return BigDecimal object whose scale will be set to 'scl'.
int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
BigDecimal quotient;
if (checkScaleNonZero((long) mcp + yscale) > xscale) {
if (checkScaleNonZero((long) mcp + yscale - xscale) > 0) {
int raise = checkScaleNonZero((long) mcp + yscale - xscale);
long scaledXs;
if ((scaledXs = longMultiplyPowerTen(xs, raise)) == INFLATED) {
......@@ -4673,7 +4677,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// return BigDecimal object whose scale will be set to 'scl'.
BigDecimal quotient;
int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
if (checkScaleNonZero((long) mcp + yscale) > xscale) {
if (checkScaleNonZero((long) mcp + yscale - xscale) > 0) {
int raise = checkScaleNonZero((long) mcp + yscale - xscale);
BigInteger rb = bigMultiplyPowerTen(xs,raise);
quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
......@@ -4714,7 +4718,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// return BigDecimal object whose scale will be set to 'scl'.
BigDecimal quotient;
int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
if (checkScaleNonZero((long) mcp + yscale) > xscale) {
if (checkScaleNonZero((long) mcp + yscale - xscale) > 0) {
int raise = checkScaleNonZero((long) mcp + yscale - xscale);
BigInteger rb = bigMultiplyPowerTen(xs,raise);
quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
......@@ -4745,7 +4749,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
// return BigDecimal object whose scale will be set to 'scl'.
BigDecimal quotient;
int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp);
if (checkScaleNonZero((long) mcp + yscale) > xscale) {
if (checkScaleNonZero((long) mcp + yscale - xscale) > 0) {
int raise = checkScaleNonZero((long) mcp + yscale - xscale);
BigInteger rb = bigMultiplyPowerTen(xs,raise);
quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale));
......
......@@ -2109,7 +2109,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
// This is a quick way to approximate the size of the result,
// similar to doing log2[n] * exponent. This will give an upper bound
// of how big the result can be, and which algorithm to use.
int scaleFactor = remainingBits * exponent;
long scaleFactor = (long)remainingBits * exponent;
// Use slightly different algorithms for small and large operands.
// See if the result will safely fit into a long. (Largest 2^63-1)
......
......@@ -50,13 +50,13 @@ import java.net.*;
* @implNote
* <p>You can use the {@code RMISocketFactory} class to create a server socket that
* is bound to a specific address, restricting the origin of requests. For example,
* the following code implements a socket factory that binds server sockets to the
* the following code implements a socket factory that binds server sockets to an IPv4
* loopback address. This restricts RMI to processing requests only from the local host.
*
* <pre>{@code
* class LoopbackSocketFactory extends RMISocketFactory {
* public ServerSocket createServerSocket(int port) throws IOException {
* return new ServerSocket(port, 5, InetAddress.getLoopbackAddress());
* return new ServerSocket(port, 5, InetAddress.getByName("127.0.0.1"));
* }
*
* public Socket createSocket(String host, int port) throws IOException {
......@@ -72,8 +72,8 @@ import java.net.*;
* }</pre>
*
* Set the {@code java.rmi.server.hostname} system property
* to a host name (typically {@code localhost}) that resolves to the loopback
* interface to ensure that the generated stubs use the right network interface.
* to {@code 127.0.0.1} to ensure that the generated stubs connect to the right
* network interface.
*
* @author Ann Wollrath
* @author Peter Jones
......
......@@ -27,7 +27,6 @@ package java.util;
import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.lang.reflect.Array;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
......@@ -35,6 +34,7 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
......@@ -1148,7 +1148,16 @@ public class Collections {
public Spliterator<E> spliterator() {
return (Spliterator<E>)c.spliterator();
}
@SuppressWarnings("unchecked")
@Override
public Stream<E> stream() {
return (Stream<E>)c.stream();
}
@SuppressWarnings("unchecked")
@Override
public Stream<E> parallelStream() {
return (Stream<E>)c.parallelStream();
}
}
/**
......@@ -2009,8 +2018,8 @@ public class Collections {
* through the returned collection.<p>
*
* It is imperative that the user manually synchronize on the returned
* collection when traversing it via {@link Iterator} or
* {@link Spliterator}:
* collection when traversing it via {@link Iterator}, {@link Spliterator}
* or {@link Stream}:
* <pre>
* Collection c = Collections.synchronizedCollection(myCollection);
* ...
......@@ -2120,6 +2129,14 @@ public class Collections {
public Spliterator<E> spliterator() {
return c.spliterator(); // Must be manually synched by user!
}
@Override
public Stream<E> stream() {
return c.stream(); // Must be manually synched by user!
}
@Override
public Stream<E> parallelStream() {
return c.parallelStream(); // Must be manually synched by user!
}
private void writeObject(ObjectOutputStream s) throws IOException {
synchronized (mutex) {s.defaultWriteObject();}
}
......@@ -3172,6 +3189,10 @@ public class Collections {
}
@Override
public Spliterator<E> spliterator() {return c.spliterator();}
@Override
public Stream<E> stream() {return c.stream();}
@Override
public Stream<E> parallelStream() {return c.parallelStream();}
}
/**
......@@ -5096,6 +5117,22 @@ public class Collections {
") > toIndex(" + toIndex + ")");
return new CopiesList<>(toIndex - fromIndex, element);
}
// Override default methods in Collection
@Override
public Stream<E> stream() {
return IntStream.range(0, n).mapToObj(i -> element);
}
@Override
public Stream<E> parallelStream() {
return IntStream.range(0, n).parallel().mapToObj(i -> element);
}
@Override
public Spliterator<E> spliterator() {
return stream().spliterator();
}
}
/**
......@@ -5503,6 +5540,10 @@ public class Collections {
@Override
public Spliterator<E> spliterator() {return s.spliterator();}
@Override
public Stream<E> stream() {return s.stream();}
@Override
public Stream<E> parallelStream() {return s.parallelStream();}
private static final long serialVersionUID = 2454657854757543876L;
......@@ -5568,10 +5609,14 @@ public class Collections {
@Override
public void forEach(Consumer<? super E> action) {q.forEach(action);}
@Override
public Spliterator<E> spliterator() {return q.spliterator();}
@Override
public boolean removeIf(Predicate<? super E> filter) {
return q.removeIf(filter);
}
@Override
public Spliterator<E> spliterator() {return q.spliterator();}
@Override
public Stream<E> stream() {return q.stream();}
@Override
public Stream<E> parallelStream() {return q.parallelStream();}
}
}
/*
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2009 Google Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
......@@ -146,7 +147,7 @@ class ComparableTimSort {
*/
int stackLen = (len < 120 ? 5 :
len < 1542 ? 10 :
len < 119151 ? 19 : 40);
len < 119151 ? 24 : 40);
runBase = new int[stackLen];
runLen = new int[stackLen];
}
......
......@@ -199,7 +199,7 @@ public interface Comparator<T> {
* composed using following code,
*
* <pre>{@code
* Comparator<String> cmp = Comparator.comparing(String::length)
* Comparator<String> cmp = Comparator.comparingInt(String::length)
* .thenComparing(String.CASE_INSENSITIVE_ORDER);
* }</pre>
*
......@@ -270,18 +270,18 @@ public interface Comparator<T> {
* extracts a {@code int} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor))}.
* thenComparing(comparingInt(keyExtractor))}.
*
* @param keyExtractor the function used to extract the integer sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code int} sort key
* @throws NullPointerException if the argument is null.
* @see #comparing(ToIntFunction)
* @see #comparingInt(ToIntFunction)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default Comparator<T> thenComparing(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparing(keyExtractor));
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}
/**
......@@ -289,18 +289,18 @@ public interface Comparator<T> {
* extracts a {@code long} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor))}.
* thenComparing(comparingLong(keyExtractor))}.
*
* @param keyExtractor the function used to extract the long sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code long} sort key
* @throws NullPointerException if the argument is null.
* @see #comparing(ToLongFunction)
* @see #comparingLong(ToLongFunction)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default Comparator<T> thenComparing(ToLongFunction<? super T> keyExtractor) {
return thenComparing(comparing(keyExtractor));
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
return thenComparing(comparingLong(keyExtractor));
}
/**
......@@ -308,18 +308,18 @@ public interface Comparator<T> {
* extracts a {@code double} sort key.
*
* @implSpec This default implementation behaves as if {@code
* thenComparing(comparing(keyExtractor))}.
* thenComparing(comparingDouble(keyExtractor))}.
*
* @param keyExtractor the function used to extract the double sort key
* @return a lexicographic-order comparator composed of this and then the
* {@code double} sort key
* @throws NullPointerException if the argument is null.
* @see #comparing(ToDoubleFunction)
* @see #comparingDouble(ToDoubleFunction)
* @see #thenComparing(Comparator)
* @since 1.8
*/
default Comparator<T> thenComparing(ToDoubleFunction<? super T> keyExtractor) {
return thenComparing(comparing(keyExtractor));
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
return thenComparing(comparingDouble(keyExtractor));
}
/**
......@@ -484,7 +484,7 @@ public interface Comparator<T> {
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static <T> Comparator<T> comparing(ToIntFunction<? super T> keyExtractor) {
public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
......@@ -505,7 +505,7 @@ public interface Comparator<T> {
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static <T> Comparator<T> comparing(ToLongFunction<? super T> keyExtractor) {
public static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
......@@ -526,7 +526,7 @@ public interface Comparator<T> {
* @throws NullPointerException if the argument is null
* @since 1.8
*/
public static<T> Comparator<T> comparing(ToDoubleFunction<? super T> keyExtractor) {
public static<T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
......
......@@ -26,9 +26,13 @@
package java.util;
import java.io.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.StreamSupport;
import sun.misc.Unsafe;
......@@ -85,6 +89,13 @@ class Random implements java.io.Serializable {
private static final long addend = 0xBL;
private static final long mask = (1L << 48) - 1;
private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
// IllegalArgumentException messages
static final String BadBound = "bound must be positive";
static final String BadRange = "bound must be greater than origin";
static final String BadSize = "size must be non-negative";
/**
* Creates a new random number generator. This constructor sets
* the seed of the random number generator to a value very likely
......@@ -221,6 +232,82 @@ class Random implements java.io.Serializable {
bytes[i++] = (byte)rnd;
}
/**
* The form of nextLong used by LongStream Spliterators. If
* origin is greater than bound, acts as unbounded form of
* nextLong, else as bounded form.
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final long internalNextLong(long origin, long bound) {
long r = nextLong();
if (origin < bound) {
long n = bound - origin, m = n - 1;
if ((n & m) == 0L) // power of two
r = (r & m) + origin;
else if (n > 0L) { // reject over-represented candidates
for (long u = r >>> 1; // ensure nonnegative
u + m - (r = u % n) < 0L; // rejection check
u = nextLong() >>> 1) // retry
;
r += origin;
}
else { // range not representable as long
while (r < origin || r >= bound)
r = nextLong();
}
}
return r;
}
/**
* The form of nextInt used by IntStream Spliterators.
* For the unbounded case: uses nextInt().
* For the bounded case with representable range: uses nextInt(int bound)
* For the bounded case with unrepresentable range: uses nextInt()
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final int internalNextInt(int origin, int bound) {
if (origin < bound) {
int n = bound - origin;
if (n > 0) {
return nextInt(n) + origin;
}
else { // range not representable as int
int r;
do {
r = nextInt();
} while (r < origin || r >= bound);
return r;
}
}
else {
return nextInt();
}
}
/**
* The form of nextDouble used by DoubleStream Spliterators.
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final double internalNextDouble(double origin, double bound) {
double r = nextDouble();
if (origin < bound) {
r = r * (bound - origin) + origin;
if (r >= bound) // correct for rounding
r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
}
return r;
}
/**
* Returns the next pseudorandom, uniformly distributed {@code int}
* value from this random number generator's sequence. The general
......@@ -247,23 +334,23 @@ class Random implements java.io.Serializable {
* between 0 (inclusive) and the specified value (exclusive), drawn from
* this random number generator's sequence. The general contract of
* {@code nextInt} is that one {@code int} value in the specified range
* is pseudorandomly generated and returned. All {@code n} possible
* is pseudorandomly generated and returned. All {@code bound} possible
* {@code int} values are produced with (approximately) equal
* probability. The method {@code nextInt(int n)} is implemented by
* probability. The method {@code nextInt(int bound)} is implemented by
* class {@code Random} as if by:
* <pre> {@code
* public int nextInt(int n) {
* if (n <= 0)
* throw new IllegalArgumentException("n must be positive");
* public int nextInt(int bound) {
* if (bound <= 0)
* throw new IllegalArgumentException("bound must be positive");
*
* if ((n & -n) == n) // i.e., n is a power of 2
* return (int)((n * (long)next(31)) >> 31);
* if ((bound & -bound) == bound) // i.e., bound is a power of 2
* return (int)((bound * (long)next(31)) >> 31);
*
* int bits, val;
* do {
* bits = next(31);
* val = bits % n;
* } while (bits - val + (n-1) < 0);
* val = bits % bound;
* } while (bits - val + (bound-1) < 0);
* return val;
* }}</pre>
*
......@@ -289,28 +376,28 @@ class Random implements java.io.Serializable {
* greatly increases the length of the sequence of values returned by
* successive calls to this method if n is a small power of two.
*
* @param n the bound on the random number to be returned. Must be
* positive.
* @param bound the upper bound (exclusive). Must be positive.
* @return the next pseudorandom, uniformly distributed {@code int}
* value between {@code 0} (inclusive) and {@code n} (exclusive)
* value between zero (inclusive) and {@code bound} (exclusive)
* from this random number generator's sequence
* @throws IllegalArgumentException if n is not positive
* @throws IllegalArgumentException if bound is not positive
* @since 1.2
*/
public int nextInt(int bound) {
if (bound <= 0)
throw new IllegalArgumentException(BadBound);
public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n-1) < 0);
return val;
int r = next(31);
int m = bound - 1;
if ((bound & m) == 0) // i.e., bound is a power of 2
r = (int)((bound * (long)r) >> 31);
else {
for (int u = r;
u - (r = u % bound) + m < 0;
u = next(31))
;
}
return r;
}
/**
......@@ -442,8 +529,7 @@ class Random implements java.io.Serializable {
* @see Math#random
*/
public double nextDouble() {
return (((long)(next(26)) << 27) + next(27))
/ (double)(1L << 53);
return (((long)(next(26)) << 27) + next(27)) * DOUBLE_UNIT;
}
private double nextNextGaussian;
......@@ -513,57 +599,563 @@ class Random implements java.io.Serializable {
}
}
// stream methods, coded in a way intended to better isolate for
// maintenance purposes the small differences across forms.
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code int} values.
*
* <p>A pseudorandom {@code int} value is generated as if it's the result of
* calling the method {@link #nextInt()}.
*
* @param streamSize the number of values to generate
* @return a stream of pseudorandom {@code int} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
* @since 1.8
*/
public IntStream ints(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, streamSize, Integer.MAX_VALUE, 0),
false);
}
/**
* Returns a stream of pseudorandom, uniformly distributed
* {@code integer} values from this random number generator's
* sequence. Values are obtained as needed by calling
* {@link #nextInt()}.
* Returns an effectively unlimited stream of pseudorandom {@code int}
* values.
*
* <p>A pseudorandom {@code int} value is generated as if it's the result of
* calling the method {@link #nextInt()}.
*
* @implNote This method is implemented to be equivalent to {@code
* ints(Long.MAX_VALUE)}.
*
* @return an infinite stream of {@code integer} values
* @return a stream of pseudorandom {@code int} values
* @since 1.8
*/
public IntStream ints() {
return IntStream.generate(this::nextInt);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number
* of pseudorandom {@code int} values, each conforming to the given
* origin (inclusive) and bound (exclusive).
*
* <p>A pseudorandom {@code int} value is generated as if it's the result of
* calling the following method with the origin and bound:
* <pre> {@code
* int nextInt(int origin, int bound) {
* int n = bound - origin;
* if (n > 0) {
* return nextInt(n) + origin;
* }
* else { // range not representable as int
* int r;
* do {
* r = nextInt();
* } while (r < origin || r >= bound);
* return r;
* }
* }}</pre>
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code int} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero, or {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public IntStream ints(long streamSize, int randomNumberOrigin,
int randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* int} values, each conforming to the given origin (inclusive) and bound
* (exclusive).
*
* <p>A pseudorandom {@code int} value is generated as if it's the result of
* calling the following method with the origin and bound:
* <pre> {@code
* int nextInt(int origin, int bound) {
* int n = bound - origin;
* if (n > 0) {
* return nextInt(n) + origin;
* }
* else { // range not representable as int
* int r;
* do {
* r = nextInt();
* } while (r < origin || r >= bound);
* return r;
* }
* }}</pre>
*
* @implNote This method is implemented to be equivalent to {@code
* ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code int} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns a stream of pseudorandom, uniformly distributed
* {@code long} values from this random number generator's
* sequence. Values are obtained as needed by calling
* {@link #nextLong()}.
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code long} values.
*
* <p>A pseudorandom {@code long} value is generated as if it's the result
* of calling the method {@link #nextLong()}.
*
* @return an infinite stream of {@code long} values
* @param streamSize the number of values to generate
* @return a stream of pseudorandom {@code long} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
* @since 1.8
*/
public LongStream longs(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, streamSize, Long.MAX_VALUE, 0L),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code long}
* values.
*
* <p>A pseudorandom {@code long} value is generated as if it's the result
* of calling the method {@link #nextLong()}.
*
* @implNote This method is implemented to be equivalent to {@code
* longs(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code long} values
* @since 1.8
*/
public LongStream longs() {
return LongStream.generate(this::nextLong);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code long}, each conforming to the given origin
* (inclusive) and bound (exclusive).
*
* <p>A pseudorandom {@code long} value is generated as if it's the result
* of calling the following method with the origin and bound:
* <pre> {@code
* long nextLong(long origin, long bound) {
* long r = nextLong();
* long n = bound - origin, m = n - 1;
* if ((n & m) == 0L) // power of two
* r = (r & m) + origin;
* else if (n > 0L) { // reject over-represented candidates
* for (long u = r >>> 1; // ensure nonnegative
* u + m - (r = u % n) < 0L; // rejection check
* u = nextLong() >>> 1) // retry
* ;
* r += origin;
* }
* else { // range not representable as long
* while (r < origin || r >= bound)
* r = nextLong();
* }
* return r;
* }}</pre>
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code long} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero, or {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public LongStream longs(long streamSize, long randomNumberOrigin,
long randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* long} values, each conforming to the given origin (inclusive) and bound
* (exclusive).
*
* <p>A pseudorandom {@code long} value is generated as if it's the result
* of calling the following method with the origin and bound:
* <pre> {@code
* long nextLong(long origin, long bound) {
* long r = nextLong();
* long n = bound - origin, m = n - 1;
* if ((n & m) == 0L) // power of two
* r = (r & m) + origin;
* else if (n > 0L) { // reject over-represented candidates
* for (long u = r >>> 1; // ensure nonnegative
* u + m - (r = u % n) < 0L; // rejection check
* u = nextLong() >>> 1) // retry
* ;
* r += origin;
* }
* else { // range not representable as long
* while (r < origin || r >= bound)
* r = nextLong();
* }
* return r;
* }}</pre>
*
* @implNote This method is implemented to be equivalent to {@code
* longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code long} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns a stream of pseudorandom, uniformly distributed
* {@code double} values between {@code 0.0} and {@code 1.0}
* from this random number generator's sequence. Values are
* obtained as needed by calling {@link #nextDouble()}.
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code double} values, each between zero
* (inclusive) and one (exclusive).
*
* @return an infinite stream of {@code double} values
* <p>A pseudorandom {@code double} value is generated as if it's the result
* of calling the method {@link #nextDouble()}}.
*
* @param streamSize the number of values to generate
* @return a stream of {@code double} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
* @since 1.8
*/
public DoubleStream doubles(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, streamSize, Double.MAX_VALUE, 0.0),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* double} values, each between zero (inclusive) and one
* (exclusive).
*
* <p>A pseudorandom {@code double} value is generated as if it's the result
* of calling the method {@link #nextDouble()}}.
*
* @implNote This method is implemented to be equivalent to {@code
* doubles(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code double} values
* @since 1.8
*/
public DoubleStream doubles() {
return DoubleStream.generate(this::nextDouble);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code double} values, each conforming to the given origin
* (inclusive) and bound (exclusive).
*
* <p>A pseudorandom {@code double} value is generated as if it's the result
* of calling the following method with the origin and bound:
* <pre> {@code
* double nextDouble(double origin, double bound) {
* double r = nextDouble();
* r = r * (bound - origin) + origin;
* if (r >= bound) // correct for rounding
* r = Math.nextDown(bound);
* return r;
* }}</pre>
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public DoubleStream doubles(long streamSize, double randomNumberOrigin,
double randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (!(randomNumberOrigin < randomNumberBound))
throw new IllegalArgumentException(BadRange);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns a stream of pseudorandom, Gaussian ("normally")
* distributed {@code double} values with mean {@code 0.0}
* and standard deviation {@code 1.0} from this random number
* generator's sequence. Values are obtained as needed by
* calling {@link #nextGaussian()}.
* Returns an effectively unlimited stream of pseudorandom {@code
* double} values, each conforming to the given origin (inclusive) and bound
* (exclusive).
*
* <p>A pseudorandom {@code double} value is generated as if it's the result
* of calling the following method with the origin and bound:
* <pre> {@code
* double nextDouble(double origin, double bound) {
* double r = nextDouble();
* r = r * (bound - origin) + origin;
* if (r >= bound) // correct for rounding
* r = Math.nextDown(bound);
* return r;
* }}</pre>
*
* @implNote This method is implemented to be equivalent to {@code
* doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @return an infinite stream of {@code double} values
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public DoubleStream gaussians() {
return DoubleStream.generate(this::nextGaussian);
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
if (!(randomNumberOrigin < randomNumberBound))
throw new IllegalArgumentException(BadRange);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Spliterator for int streams. We multiplex the four int
* versions into one class by treating a bound less than origin as
* unbounded, and also by treating "infinite" as equivalent to
* Long.MAX_VALUE. For splits, it uses the standard divide-by-two
* approach. The long and double versions of this class are
* identical except for types.
*/
static final class RandomIntsSpliterator implements Spliterator.OfInt {
final Random rng;
long index;
final long fence;
final int origin;
final int bound;
RandomIntsSpliterator(Random rng, long index, long fence,
int origin, int bound) {
this.rng = rng; this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomIntsSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomIntsSpliterator(rng, i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(IntConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(rng.internalNextInt(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(IntConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
Random r = rng;
int o = origin, b = bound;
do {
consumer.accept(r.internalNextInt(o, b));
} while (++i < f);
}
}
}
/**
* Spliterator for long streams.
*/
static final class RandomLongsSpliterator implements Spliterator.OfLong {
final Random rng;
long index;
final long fence;
final long origin;
final long bound;
RandomLongsSpliterator(Random rng, long index, long fence,
long origin, long bound) {
this.rng = rng; this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomLongsSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomLongsSpliterator(rng, i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(LongConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(rng.internalNextLong(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(LongConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
Random r = rng;
long o = origin, b = bound;
do {
consumer.accept(r.internalNextLong(o, b));
} while (++i < f);
}
}
}
/**
* Spliterator for double streams.
*/
static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
final Random rng;
long index;
final long fence;
final double origin;
final double bound;
RandomDoublesSpliterator(Random rng, long index, long fence,
double origin, double bound) {
this.rng = rng; this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomDoublesSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomDoublesSpliterator(rng, i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(DoubleConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(rng.internalNextDouble(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(DoubleConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
Random r = rng;
double o = origin, b = bound;
do {
consumer.accept(r.internalNextDouble(o, b));
} while (++i < f);
}
}
}
/**
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.util;
import java.security.SecureRandom;
import java.net.InetAddress;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
import java.util.function.DoubleConsumer;
import java.util.stream.StreamSupport;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.DoubleStream;
/**
* A generator of uniform pseudorandom values applicable for use in
* (among other contexts) isolated parallel computations that may
* generate subtasks. Class {@code SplittableRandom} supports methods for
* producing pseudorandom numbers of type {@code int}, {@code long},
* and {@code double} with similar usages as for class
* {@link java.util.Random} but differs in the following ways:
*
* <ul>
*
* <li>Series of generated values pass the DieHarder suite testing
* independence and uniformity properties of random number generators.
* (Most recently validated with <a
* href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> version
* 3.31.1</a>.) These tests validate only the methods for certain
* types and ranges, but similar properties are expected to hold, at
* least approximately, for others as well. The <em>period</em>
* (length of any series of generated values before it repeats) is at
* least 2<sup>64</sup>. </li>
*
* <li> Method {@link #split} constructs and returns a new
* SplittableRandom instance that shares no mutable state with the
* current instance. However, with very high probability, the
* values collectively generated by the two objects have the same
* statistical properties as if the same quantity of values were
* generated by a single thread using a single {@code
* SplittableRandom} object. </li>
*
* <li>Instances of SplittableRandom are <em>not</em> thread-safe.
* They are designed to be split, not shared, across threads. For
* example, a {@link java.util.concurrent.ForkJoinTask
* fork/join-style} computation using random numbers might include a
* construction of the form {@code new
* Subtask(aSplittableRandom.split()).fork()}.
*
* <li>This class provides additional methods for generating random
* streams, that employ the above techniques when used in {@code
* stream.parallel()} mode.</li>
*
* </ul>
*
* <p>Instances of {@code SplittableRandom} are not cryptographically
* secure. Consider instead using {@link java.security.SecureRandom}
* in security-sensitive applications. Additionally,
* default-constructed instances do not use a cryptographically random
* seed unless the {@linkplain System#getProperty system property}
* {@code java.util.secureRandomSeed} is set to {@code true}.
*
* @author Guy Steele
* @author Doug Lea
* @since 1.8
*/
public final class SplittableRandom {
/*
* Implementation Overview.
*
* This algorithm was inspired by the "DotMix" algorithm by
* Leiserson, Schardl, and Sukha "Deterministic Parallel
* Random-Number Generation for Dynamic-Multithreading Platforms",
* PPoPP 2012, as well as those in "Parallel random numbers: as
* easy as 1, 2, 3" by Salmon, Morae, Dror, and Shaw, SC 2011. It
* differs mainly in simplifying and cheapening operations.
*
* The primary update step (method nextSeed()) is to add a
* constant ("gamma") to the current (64 bit) seed, forming a
* simple sequence. The seed and the gamma values for any two
* SplittableRandom instances are highly likely to be different.
*
* Methods nextLong, nextInt, and derivatives do not return the
* sequence (seed) values, but instead a hash-like bit-mix of
* their bits, producing more independently distributed sequences.
* For nextLong, the mix64 bit-mixing function computes the same
* value as the "64-bit finalizer" function in Austin Appleby's
* MurmurHash3 algorithm. See
* http://code.google.com/p/smhasher/wiki/MurmurHash3 , which
* comments: "The constants for the finalizers were generated by a
* simple simulated-annealing algorithm, and both avalanche all
* bits of 'h' to within 0.25% bias." The mix32 function is
* equivalent to (int)(mix64(seed) >>> 32), but faster because it
* omits a step that doesn't contribute to result.
*
* The split operation uses the current generator to form the seed
* and gamma for another SplittableRandom. To conservatively
* avoid potential correlations between seed and value generation,
* gamma selection (method nextGamma) uses the "Mix13" constants
* for MurmurHash3 described by David Stafford
* (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)
* To avoid potential weaknesses in bit-mixing transformations, we
* restrict gammas to odd values with at least 12 and no more than
* 52 bits set. Rather than rejecting candidates with too few or
* too many bits set, method nextGamma flips some bits (which has
* the effect of mapping at most 4 to any given gamma value).
* This reduces the effective set of 64bit odd gamma values by
* about 2<sup>14</sup>, a very tiny percentage, and serves as an
* automated screening for sequence constant selection that is
* left as an empirical decision in some other hashing and crypto
* algorithms.
*
* The resulting generator thus transforms a sequence in which
* (typically) many bits change on each step, with an inexpensive
* mixer with good (but less than cryptographically secure)
* avalanching.
*
* The default (no-argument) constructor, in essence, invokes
* split() for a common "seeder" SplittableRandom. Unlike other
* cases, this split must be performed in a thread-safe manner, so
* we use an AtomicLong to represent the seed rather than use an
* explicit SplittableRandom. To bootstrap the seeder, we start
* off using a seed based on current time and host unless the
* java.util.secureRandomSeed property is set. This serves as a
* slimmed-down (and insecure) variant of SecureRandom that also
* avoids stalls that may occur when using /dev/random.
*
* It is a relatively simple matter to apply the basic design here
* to use 128 bit seeds. However, emulating 128bit arithmetic and
* carrying around twice the state add more overhead than appears
* warranted for current usages.
*
* File organization: First the non-public methods that constitute
* the main algorithm, then the main public methods, followed by
* some custom spliterator classes needed for stream methods.
*/
/**
* The initial gamma value for (unsplit) SplittableRandoms. Must
* be odd with at least 12 and no more than 52 bits set. Currently
* set to the golden ratio scaled to 64bits.
*/
private static final long INITIAL_GAMMA = 0x9e3779b97f4a7c15L;
/**
* The least non-zero value returned by nextDouble(). This value
* is scaled by a random value of 53 bits to produce a result.
*/
private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
/**
* The seed. Updated only via method nextSeed.
*/
private long seed;
/**
* The step value.
*/
private final long gamma;
/**
* Internal constructor used by all others except default constructor.
*/
private SplittableRandom(long seed, long gamma) {
this.seed = seed;
this.gamma = gamma;
}
/**
* Computes MurmurHash3 64bit mix function.
*/
private static long mix64(long z) {
z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
return z ^ (z >>> 33);
}
/**
* Returns the 32 high bits of mix64(z) as int.
*/
private static int mix32(long z) {
z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);
}
/**
* Returns the gamma value to use for a new split instance.
*/
private static long nextGamma(long z) {
z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L; // Stafford "Mix13"
z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
z = (z ^ (z >>> 31)) | 1L; // force to be odd
int n = Long.bitCount(z); // ensure enough 0 and 1 bits
return (n < 12 || n > 52) ? z ^ 0xaaaaaaaaaaaaaaaaL : z;
}
/**
* Adds gamma to seed.
*/
private long nextSeed() {
return seed += gamma;
}
/**
* The seed generator for default constructors.
*/
private static final AtomicLong seeder = new AtomicLong(initialSeed());
private static long initialSeed() {
String pp = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction(
"java.util.secureRandomSeed"));
if (pp != null && pp.equalsIgnoreCase("true")) {
byte[] seedBytes = java.security.SecureRandom.getSeed(8);
long s = (long)(seedBytes[0]) & 0xffL;
for (int i = 1; i < 8; ++i)
s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
return s;
}
int hh = 0; // hashed host address
try {
hh = InetAddress.getLocalHost().hashCode();
} catch (Exception ignore) {
}
return (mix64((((long)hh) << 32) ^ System.currentTimeMillis()) ^
mix64(System.nanoTime()));
}
// IllegalArgumentException messages
static final String BadBound = "bound must be positive";
static final String BadRange = "bound must be greater than origin";
static final String BadSize = "size must be non-negative";
/*
* Internal versions of nextX methods used by streams, as well as
* the public nextX(origin, bound) methods. These exist mainly to
* avoid the need for multiple versions of stream spliterators
* across the different exported forms of streams.
*/
/**
* The form of nextLong used by LongStream Spliterators. If
* origin is greater than bound, acts as unbounded form of
* nextLong, else as bounded form.
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final long internalNextLong(long origin, long bound) {
/*
* Four Cases:
*
* 1. If the arguments indicate unbounded form, act as
* nextLong().
*
* 2. If the range is an exact power of two, apply the
* associated bit mask.
*
* 3. If the range is positive, loop to avoid potential bias
* when the implicit nextLong() bound (2<sup>64</sup>) is not
* evenly divisible by the range. The loop rejects candidates
* computed from otherwise over-represented values. The
* expected number of iterations under an ideal generator
* varies from 1 to 2, depending on the bound. The loop itself
* takes an unlovable form. Because the first candidate is
* already available, we need a break-in-the-middle
* construction, which is concisely but cryptically performed
* within the while-condition of a body-less for loop.
*
* 4. Otherwise, the range cannot be represented as a positive
* long. The loop repeatedly generates unbounded longs until
* obtaining a candidate meeting constraints (with an expected
* number of iterations of less than two).
*/
long r = mix64(nextSeed());
if (origin < bound) {
long n = bound - origin, m = n - 1;
if ((n & m) == 0L) // power of two
r = (r & m) + origin;
else if (n > 0L) { // reject over-represented candidates
for (long u = r >>> 1; // ensure nonnegative
u + m - (r = u % n) < 0L; // rejection check
u = mix64(nextSeed()) >>> 1) // retry
;
r += origin;
}
else { // range not representable as long
while (r < origin || r >= bound)
r = mix64(nextSeed());
}
}
return r;
}
/**
* The form of nextInt used by IntStream Spliterators.
* Exactly the same as long version, except for types.
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final int internalNextInt(int origin, int bound) {
int r = mix32(nextSeed());
if (origin < bound) {
int n = bound - origin, m = n - 1;
if ((n & m) == 0)
r = (r & m) + origin;
else if (n > 0) {
for (int u = r >>> 1;
u + m - (r = u % n) < 0;
u = mix32(nextSeed()) >>> 1)
;
r += origin;
}
else {
while (r < origin || r >= bound)
r = mix32(nextSeed());
}
}
return r;
}
/**
* The form of nextDouble used by DoubleStream Spliterators.
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final double internalNextDouble(double origin, double bound) {
double r = (nextLong() >>> 11) * DOUBLE_UNIT;
if (origin < bound) {
r = r * (bound - origin) + origin;
if (r >= bound) // correct for rounding
r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
}
return r;
}
/* ---------------- public methods ---------------- */
/**
* Creates a new SplittableRandom instance using the specified
* initial seed. SplittableRandom instances created with the same
* seed in the same program generate identical sequences of values.
*
* @param seed the initial seed
*/
public SplittableRandom(long seed) {
this(seed, INITIAL_GAMMA);
}
/**
* Creates a new SplittableRandom instance that is likely to
* generate sequences of values that are statistically independent
* of those of any other instances in the current program; and
* may, and typically does, vary across program invocations.
*/
public SplittableRandom() { // emulate seeder.split()
this.gamma = nextGamma(this.seed = seeder.addAndGet(INITIAL_GAMMA));
}
/**
* Constructs and returns a new SplittableRandom instance that
* shares no mutable state with this instance. However, with very
* high probability, the set of values collectively generated by
* the two objects has the same statistical properties as if the
* same quantity of values were generated by a single thread using
* a single SplittableRandom object. Either or both of the two
* objects may be further split using the {@code split()} method,
* and the same expected statistical properties apply to the
* entire set of generators constructed by such recursive
* splitting.
*
* @return the new SplittableRandom instance
*/
public SplittableRandom split() {
long s = nextSeed();
return new SplittableRandom(s, nextGamma(s));
}
/**
* Returns a pseudorandom {@code int} value.
*
* @return a pseudorandom {@code int} value
*/
public int nextInt() {
return mix32(nextSeed());
}
/**
* Returns a pseudorandom {@code int} value between zero (inclusive)
* and the specified bound (exclusive).
*
* @param bound the upper bound (exclusive). Must be positive.
* @return a pseudorandom {@code int} value between zero
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code bound} is not positive
*/
public int nextInt(int bound) {
if (bound <= 0)
throw new IllegalArgumentException(BadBound);
// Specialize internalNextInt for origin 0
int r = mix32(nextSeed());
int m = bound - 1;
if ((bound & m) == 0) // power of two
r &= m;
else { // reject over-represented candidates
for (int u = r >>> 1;
u + m - (r = u % bound) < 0;
u = mix32(nextSeed()) >>> 1)
;
}
return r;
}
/**
* Returns a pseudorandom {@code int} value between the specified
* origin (inclusive) and the specified bound (exclusive).
*
* @param origin the least value returned
* @param bound the upper bound (exclusive)
* @return a pseudorandom {@code int} value between the origin
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*/
public int nextInt(int origin, int bound) {
if (origin >= bound)
throw new IllegalArgumentException(BadRange);
return internalNextInt(origin, bound);
}
/**
* Returns a pseudorandom {@code long} value.
*
* @return a pseudorandom {@code long} value
*/
public long nextLong() {
return mix64(nextSeed());
}
/**
* Returns a pseudorandom {@code long} value between zero (inclusive)
* and the specified bound (exclusive).
*
* @param bound the upper bound (exclusive). Must be positive.
* @return a pseudorandom {@code long} value between zero
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code bound} is not positive
*/
public long nextLong(long bound) {
if (bound <= 0)
throw new IllegalArgumentException(BadBound);
// Specialize internalNextLong for origin 0
long r = mix64(nextSeed());
long m = bound - 1;
if ((bound & m) == 0L) // power of two
r &= m;
else { // reject over-represented candidates
for (long u = r >>> 1;
u + m - (r = u % bound) < 0L;
u = mix64(nextSeed()) >>> 1)
;
}
return r;
}
/**
* Returns a pseudorandom {@code long} value between the specified
* origin (inclusive) and the specified bound (exclusive).
*
* @param origin the least value returned
* @param bound the upper bound (exclusive)
* @return a pseudorandom {@code long} value between the origin
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*/
public long nextLong(long origin, long bound) {
if (origin >= bound)
throw new IllegalArgumentException(BadRange);
return internalNextLong(origin, bound);
}
/**
* Returns a pseudorandom {@code double} value between zero
* (inclusive) and one (exclusive).
*
* @return a pseudorandom {@code double} value between zero
* (inclusive) and one (exclusive)
*/
public double nextDouble() {
return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
}
/**
* Returns a pseudorandom {@code double} value between 0.0
* (inclusive) and the specified bound (exclusive).
*
* @param bound the upper bound (exclusive). Must be positive.
* @return a pseudorandom {@code double} value between zero
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code bound} is not positive
*/
public double nextDouble(double bound) {
if (!(bound > 0.0))
throw new IllegalArgumentException(BadBound);
double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
return (result < bound) ? result : // correct for rounding
Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
}
/**
* Returns a pseudorandom {@code double} value between the specified
* origin (inclusive) and bound (exclusive).
*
* @param origin the least value returned
* @param bound the upper bound (exclusive)
* @return a pseudorandom {@code double} value between the origin
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*/
public double nextDouble(double origin, double bound) {
if (!(origin < bound))
throw new IllegalArgumentException(BadRange);
return internalNextDouble(origin, bound);
}
/**
* Returns a pseudorandom {@code boolean} value.
*
* @return a pseudorandom {@code boolean} value
*/
public boolean nextBoolean() {
return mix32(nextSeed()) < 0;
}
// stream methods, coded in a way intended to better isolate for
// maintenance purposes the small differences across forms.
/**
* Returns a stream producing the given {@code streamSize} number
* of pseudorandom {@code int} values from this generator and/or
* one split from it.
*
* @param streamSize the number of values to generate
* @return a stream of pseudorandom {@code int} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
*/
public IntStream ints(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, streamSize, Integer.MAX_VALUE, 0),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code int}
* values from this generator and/or one split from it.
*
* @implNote This method is implemented to be equivalent to {@code
* ints(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code int} values
*/
public IntStream ints() {
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number
* of pseudorandom {@code int} values from this generator and/or one split
* from it; each value conforms to the given origin (inclusive) and bound
* (exclusive).
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code int} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero, or {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public IntStream ints(long streamSize, int randomNumberOrigin,
int randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* int} values from this generator and/or one split from it; each value
* conforms to the given origin (inclusive) and bound (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code int} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number
* of pseudorandom {@code long} values from this generator and/or
* one split from it.
*
* @param streamSize the number of values to generate
* @return a stream of pseudorandom {@code long} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
*/
public LongStream longs(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, streamSize, Long.MAX_VALUE, 0L),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* long} values from this generator and/or one split from it.
*
* @implNote This method is implemented to be equivalent to {@code
* longs(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code long} values
*/
public LongStream longs() {
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code long} values from this generator and/or one split
* from it; each value conforms to the given origin (inclusive) and bound
* (exclusive).
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code long} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero, or {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public LongStream longs(long streamSize, long randomNumberOrigin,
long randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* long} values from this generator and/or one split from it; each value
* conforms to the given origin (inclusive) and bound (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code long} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code double} values from this generator and/or one split
* from it; each value is between zero (inclusive) and one (exclusive).
*
* @param streamSize the number of values to generate
* @return a stream of {@code double} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
*/
public DoubleStream doubles(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, streamSize, Double.MAX_VALUE, 0.0),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* double} values from this generator and/or one split from it; each value
* is between zero (inclusive) and one (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* doubles(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code double} values
*/
public DoubleStream doubles() {
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code double} values from this generator and/or one split
* from it; each value conforms to the given origin (inclusive) and bound
* (exclusive).
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public DoubleStream doubles(long streamSize, double randomNumberOrigin,
double randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (!(randomNumberOrigin < randomNumberBound))
throw new IllegalArgumentException(BadRange);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* double} values from this generator and/or one split from it; each value
* conforms to the given origin (inclusive) and bound (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
*/
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
if (!(randomNumberOrigin < randomNumberBound))
throw new IllegalArgumentException(BadRange);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Spliterator for int streams. We multiplex the four int
* versions into one class by treating a bound less than origin as
* unbounded, and also by treating "infinite" as equivalent to
* Long.MAX_VALUE. For splits, it uses the standard divide-by-two
* approach. The long and double versions of this class are
* identical except for types.
*/
static final class RandomIntsSpliterator implements Spliterator.OfInt {
final SplittableRandom rng;
long index;
final long fence;
final int origin;
final int bound;
RandomIntsSpliterator(SplittableRandom rng, long index, long fence,
int origin, int bound) {
this.rng = rng; this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomIntsSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomIntsSpliterator(rng.split(), i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(IntConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(rng.internalNextInt(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(IntConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
SplittableRandom r = rng;
int o = origin, b = bound;
do {
consumer.accept(r.internalNextInt(o, b));
} while (++i < f);
}
}
}
/**
* Spliterator for long streams.
*/
static final class RandomLongsSpliterator implements Spliterator.OfLong {
final SplittableRandom rng;
long index;
final long fence;
final long origin;
final long bound;
RandomLongsSpliterator(SplittableRandom rng, long index, long fence,
long origin, long bound) {
this.rng = rng; this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomLongsSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomLongsSpliterator(rng.split(), i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(LongConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(rng.internalNextLong(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(LongConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
SplittableRandom r = rng;
long o = origin, b = bound;
do {
consumer.accept(r.internalNextLong(o, b));
} while (++i < f);
}
}
}
/**
* Spliterator for double streams.
*/
static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
final SplittableRandom rng;
long index;
final long fence;
final double origin;
final double bound;
RandomDoublesSpliterator(SplittableRandom rng, long index, long fence,
double origin, double bound) {
this.rng = rng; this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomDoublesSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomDoublesSpliterator(rng.split(), i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(DoubleConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(rng.internalNextDouble(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(DoubleConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
SplittableRandom r = rng;
double o = origin, b = bound;
do {
consumer.accept(r.internalNextDouble(o, b));
} while (++i < f);
}
}
}
}
/*
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2009 Google Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
......@@ -176,7 +177,7 @@ class TimSort<T> {
*/
int stackLen = (len < 120 ? 5 :
len < 1542 ? 10 :
len < 119151 ? 19 : 40);
len < 119151 ? 24 : 40);
runBase = new int[stackLen];
runLen = new int[stackLen];
}
......
......@@ -972,6 +972,27 @@ public class TreeMap<K,V>
return tailMap(fromKey, true);
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
Entry<K,V> p = getEntry(key);
if (p!=null && Objects.equals(oldValue, p.value)) {
p.value = newValue;
return true;
}
return false;
}
@Override
public V replace(K key, V value) {
Entry<K,V> p = getEntry(key);
if (p!=null) {
V oldValue = p.value;
p.value = value;
return oldValue;
}
return null;
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
......
......@@ -37,11 +37,16 @@ package java.util.concurrent;
import java.io.ObjectStreamField;
import java.util.Random;
import java.util.Spliterator;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.StreamSupport;
/**
* A random number generator isolated to the current thread. Like the
......@@ -64,6 +69,10 @@ import java.util.stream.LongStream;
* <p>This class also provides additional commonly used bounded random
* generation methods.
*
* <p>Instances of {@code ThreadLocalRandom} are not cryptographically
* secure. Consider instead using {@link java.security.SecureRandom}
* in security-sensitive applications.
*
* @since 1.7
* @author Doug Lea
*/
......@@ -85,28 +94,26 @@ public class ThreadLocalRandom extends Random {
* application-level overhead and footprint of most concurrent
* programs.
*
* Even though this class subclasses java.util.Random, it uses the
* same basic algorithm as java.util.SplittableRandom. (See its
* internal documentation for explanations, which are not repeated
* here.) Because ThreadLocalRandoms are not splittable
* though, we use only a single 64bit gamma.
*
* Because this class is in a different package than class Thread,
* field access methods use Unsafe to bypass access control rules.
* The base functionality of Random methods is conveniently
* isolated in method next(bits), that just reads and writes the
* Thread field rather than its own field. However, to conform to
* the requirements of the Random superclass constructor, the
* common static ThreadLocalRandom maintains an "initialized"
* field for the sake of rejecting user calls to setSeed while
* still allowing a call from constructor. Note that
* serialization is completely unnecessary because there is only a
* static singleton. But we generate a serial form containing
* "rnd" and "initialized" fields to ensure compatibility across
* versions.
*
* Per-thread initialization is similar to that in the no-arg
* Random constructor, but we avoid correlation among not only
* initial seeds of those created in different threads, but also
* those created using class Random itself; while at the same time
* not changing any statistical properties. So we use the same
* underlying multiplicative sequence, but start the sequence far
* away from the base version, and then merge (xor) current time
* and per-thread probe bits to generate initial values.
* To conform to the requirements of the Random superclass
* constructor, the common static ThreadLocalRandom maintains an
* "initialized" field for the sake of rejecting user calls to
* setSeed while still allowing a call from constructor. Note
* that serialization is completely unnecessary because there is
* only a static singleton. But we generate a serial form
* containing "rnd" and "initialized" fields to ensure
* compatibility across versions.
*
* Implementations of non-core methods are mostly the same as in
* SplittableRandom, that were in part derived from a previous
* version of this class.
*
* The nextLocalGaussian ThreadLocal supports the very rarely used
* nextGaussian method by providing a holder for the second of a
......@@ -115,24 +122,51 @@ public class ThreadLocalRandom extends Random {
* but we provide identical statistical properties.
*/
// same constants as Random, but must be redeclared because private
private static final long multiplier = 0x5DEECE66DL;
private static final long addend = 0xBL;
private static final long mask = (1L << 48) - 1;
private static final int PROBE_INCREMENT = 0x61c88647;
/** Generates the basis for per-thread initial seed values */
private static final AtomicLong seedGenerator =
new AtomicLong(1269533684904616924L);
/** Generates per-thread initialization/probe field */
private static final AtomicInteger probeGenerator =
new AtomicInteger(0xe80f8647);
new AtomicInteger();
/**
* The next seed for default constructors.
*/
private static final AtomicLong seeder =
new AtomicLong(mix64(System.currentTimeMillis()) ^
mix64(System.nanoTime()));
/**
* The seed increment
*/
private static final long GAMMA = 0x9e3779b97f4a7c15L;
/**
* The increment for generating probe values
*/
private static final int PROBE_INCREMENT = 0x9e3779b9;
/**
* The increment of seeder per new instance
*/
private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
// Constants from SplittableRandom
private static final double DOUBLE_UNIT = 1.0 / (1L << 53);
private static final float FLOAT_UNIT = 1.0f / (1 << 24);
/** Rarely-used holder for the second of a pair of Gaussians */
private static final ThreadLocal<Double> nextLocalGaussian =
new ThreadLocal<Double>();
private static long mix64(long z) {
z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L;
return z ^ (z >>> 33);
}
private static int mix32(long z) {
z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32);
}
/**
* Field used only during singleton initialization.
* True when constructor completes.
......@@ -155,16 +189,11 @@ public class ThreadLocalRandom extends Random {
* rely on (static) atomic generators to initialize the values.
*/
static final void localInit() {
int p = probeGenerator.getAndAdd(PROBE_INCREMENT);
int p = probeGenerator.addAndGet(PROBE_INCREMENT);
int probe = (p == 0) ? 1 : p; // skip 0
long current, next;
do { // same sequence as j.u.Random but different initial value
current = seedGenerator.get();
next = current * 181783497276652981L;
} while (!seedGenerator.compareAndSet(current, next));
long r = next ^ ((long)probe << 32) ^ System.nanoTime();
long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
Thread t = Thread.currentThread();
UNSAFE.putLong(t, SEED, r);
UNSAFE.putLong(t, SEED, seed);
UNSAFE.putInt(t, PROBE, probe);
}
......@@ -191,124 +220,264 @@ public class ThreadLocalRandom extends Random {
throw new UnsupportedOperationException();
}
protected int next(int bits) {
final long nextSeed() {
Thread t; long r; // read and update per-thread seed
UNSAFE.putLong
(t = Thread.currentThread(), SEED,
r = (UNSAFE.getLong(t, SEED) * multiplier + addend) & mask);
return (int) (r >>> (48-bits));
UNSAFE.putLong(t = Thread.currentThread(), SEED,
r = UNSAFE.getLong(t, SEED) + GAMMA);
return r;
}
// We must define this, but never use it.
protected int next(int bits) {
return (int)(mix64(nextSeed()) >>> (64 - bits));
}
// IllegalArgumentException messages
static final String BadBound = "bound must be positive";
static final String BadRange = "bound must be greater than origin";
static final String BadSize = "size must be non-negative";
/**
* Returns a pseudorandom, uniformly distributed value between the
* given least value (inclusive) and bound (exclusive).
* The form of nextLong used by LongStream Spliterators. If
* origin is greater than bound, acts as unbounded form of
* nextLong, else as bounded form.
*
* @param least the least value returned
* @param bound the upper bound (exclusive)
* @throws IllegalArgumentException if least greater than or equal
* to bound
* @return the next value
*/
public int nextInt(int least, int bound) {
if (least >= bound)
throw new IllegalArgumentException();
return nextInt(bound - least) + least;
}
/**
* Returns a pseudorandom, uniformly distributed value
* between 0 (inclusive) and the specified value (exclusive).
*
* @param n the bound on the random number to be returned. Must be
* positive.
* @return the next value
* @throws IllegalArgumentException if n is not positive
*/
public long nextLong(long n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
// Divide n by two until small enough for nextInt. On each
// iteration (at most 31 of them but usually much less),
// randomly choose both whether to include high bit in result
// (offset) and whether to continue with the lower vs upper
// half (which makes a difference only if odd).
long offset = 0;
while (n >= Integer.MAX_VALUE) {
int bits = next(2);
long half = n >>> 1;
long nextn = ((bits & 2) == 0) ? half : n - half;
if ((bits & 1) == 0)
offset += n - nextn;
n = nextn;
}
return offset + nextInt((int) n);
}
@Override
public IntStream ints() {
return IntStream.generate(() -> current().nextInt());
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final long internalNextLong(long origin, long bound) {
long r = mix64(nextSeed());
if (origin < bound) {
long n = bound - origin, m = n - 1;
if ((n & m) == 0L) // power of two
r = (r & m) + origin;
else if (n > 0L) { // reject over-represented candidates
for (long u = r >>> 1; // ensure nonnegative
u + m - (r = u % n) < 0L; // rejection check
u = mix64(nextSeed()) >>> 1) // retry
;
r += origin;
}
else { // range not representable as long
while (r < origin || r >= bound)
r = mix64(nextSeed());
}
}
return r;
}
@Override
public LongStream longs() {
return LongStream.generate(() -> current().nextLong());
/**
* The form of nextInt used by IntStream Spliterators.
* Exactly the same as long version, except for types.
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final int internalNextInt(int origin, int bound) {
int r = mix32(nextSeed());
if (origin < bound) {
int n = bound - origin, m = n - 1;
if ((n & m) == 0)
r = (r & m) + origin;
else if (n > 0) {
for (int u = r >>> 1;
u + m - (r = u % n) < 0;
u = mix32(nextSeed()) >>> 1)
;
r += origin;
}
else {
while (r < origin || r >= bound)
r = mix32(nextSeed());
}
}
return r;
}
@Override
public DoubleStream doubles() {
return DoubleStream.generate(() -> current().nextDouble());
/**
* The form of nextDouble used by DoubleStream Spliterators.
*
* @param origin the least value, unless greater than bound
* @param bound the upper bound (exclusive), must not equal origin
* @return a pseudorandom value
*/
final double internalNextDouble(double origin, double bound) {
double r = (nextLong() >>> 11) * DOUBLE_UNIT;
if (origin < bound) {
r = r * (bound - origin) + origin;
if (r >= bound) // correct for rounding
r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
}
return r;
}
/**
* Returns a pseudorandom {@code int} value.
*
* @return a pseudorandom {@code int} value
*/
public int nextInt() {
return mix32(nextSeed());
}
@Override
public DoubleStream gaussians() {
return DoubleStream.generate(() -> current().nextGaussian());
/**
* Returns a pseudorandom {@code int} value between zero (inclusive)
* and the specified bound (exclusive).
*
* @param bound the upper bound (exclusive). Must be positive.
* @return a pseudorandom {@code int} value between zero
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code bound} is not positive
*/
public int nextInt(int bound) {
if (bound <= 0)
throw new IllegalArgumentException(BadBound);
int r = mix32(nextSeed());
int m = bound - 1;
if ((bound & m) == 0) // power of two
r &= m;
else { // reject over-represented candidates
for (int u = r >>> 1;
u + m - (r = u % bound) < 0;
u = mix32(nextSeed()) >>> 1)
;
}
return r;
}
/**
* Returns a pseudorandom {@code int} value between the specified
* origin (inclusive) and the specified bound (exclusive).
*
* @param origin the least value returned
* @param bound the upper bound (exclusive)
* @return a pseudorandom {@code int} value between the origin
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*/
public int nextInt(int origin, int bound) {
if (origin >= bound)
throw new IllegalArgumentException(BadRange);
return internalNextInt(origin, bound);
}
/**
* Returns a pseudorandom {@code long} value.
*
* @return a pseudorandom {@code long} value
*/
public long nextLong() {
return mix64(nextSeed());
}
/**
* Returns a pseudorandom {@code long} value between zero (inclusive)
* and the specified bound (exclusive).
*
* @param bound the upper bound (exclusive). Must be positive.
* @return a pseudorandom {@code long} value between zero
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code bound} is not positive
*/
public long nextLong(long bound) {
if (bound <= 0)
throw new IllegalArgumentException(BadBound);
long r = mix64(nextSeed());
long m = bound - 1;
if ((bound & m) == 0L) // power of two
r &= m;
else { // reject over-represented candidates
for (long u = r >>> 1;
u + m - (r = u % bound) < 0L;
u = mix64(nextSeed()) >>> 1)
;
}
return r;
}
/**
* Returns a pseudorandom, uniformly distributed value between the
* given least value (inclusive) and bound (exclusive).
* Returns a pseudorandom {@code long} value between the specified
* origin (inclusive) and the specified bound (exclusive).
*
* @param least the least value returned
* @param origin the least value returned
* @param bound the upper bound (exclusive)
* @return the next value
* @throws IllegalArgumentException if least greater than or equal
* to bound
* @return a pseudorandom {@code long} value between the origin
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*/
public long nextLong(long origin, long bound) {
if (origin >= bound)
throw new IllegalArgumentException(BadRange);
return internalNextLong(origin, bound);
}
/**
* Returns a pseudorandom {@code double} value between zero
* (inclusive) and one (exclusive).
*
* @return a pseudorandom {@code double} value between zero
* (inclusive) and one (exclusive)
*/
public long nextLong(long least, long bound) {
if (least >= bound)
throw new IllegalArgumentException();
return nextLong(bound - least) + least;
public double nextDouble() {
return (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT;
}
/**
* Returns a pseudorandom, uniformly distributed {@code double} value
* between 0 (inclusive) and the specified value (exclusive).
* Returns a pseudorandom {@code double} value between 0.0
* (inclusive) and the specified bound (exclusive).
*
* @param n the bound on the random number to be returned. Must be
* positive.
* @return the next value
* @throws IllegalArgumentException if n is not positive
* @param bound the upper bound (exclusive). Must be positive.
* @return a pseudorandom {@code double} value between zero
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code bound} is not positive
*/
public double nextDouble(double n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
return nextDouble() * n;
public double nextDouble(double bound) {
if (!(bound > 0.0))
throw new IllegalArgumentException(BadBound);
double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
return (result < bound) ? result : // correct for rounding
Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
}
/**
* Returns a pseudorandom, uniformly distributed value between the
* given least value (inclusive) and bound (exclusive).
* Returns a pseudorandom {@code double} value between the specified
* origin (inclusive) and bound (exclusive).
*
* @param least the least value returned
* @param origin the least value returned
* @param bound the upper bound (exclusive)
* @return the next value
* @throws IllegalArgumentException if least greater than or equal
* to bound
* @return a pseudorandom {@code double} value between the origin
* (inclusive) and the bound (exclusive)
* @throws IllegalArgumentException if {@code origin} is greater than
* or equal to {@code bound}
*/
public double nextDouble(double least, double bound) {
if (least >= bound)
throw new IllegalArgumentException();
return nextDouble() * (bound - least) + least;
public double nextDouble(double origin, double bound) {
if (!(origin < bound))
throw new IllegalArgumentException(BadRange);
return internalNextDouble(origin, bound);
}
/**
* Returns a pseudorandom {@code boolean} value.
*
* @return a pseudorandom {@code boolean} value
*/
public boolean nextBoolean() {
return mix32(nextSeed()) < 0;
}
/**
* Returns a pseudorandom {@code float} value between zero
* (inclusive) and one (exclusive).
*
* @return a pseudorandom {@code float} value between zero
* (inclusive) and one (exclusive)
*/
public float nextFloat() {
return (mix32(nextSeed()) >>> 8) * FLOAT_UNIT;
}
public double nextGaussian() {
......@@ -329,6 +498,445 @@ public class ThreadLocalRandom extends Random {
return v1 * multiplier;
}
// stream methods, coded in a way intended to better isolate for
// maintenance purposes the small differences across forms.
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code int} values.
*
* @param streamSize the number of values to generate
* @return a stream of pseudorandom {@code int} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
* @since 1.8
*/
public IntStream ints(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.intStream
(new RandomIntsSpliterator
(0L, streamSize, Integer.MAX_VALUE, 0),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code int}
* values.
*
* @implNote This method is implemented to be equivalent to {@code
* ints(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code int} values
* @since 1.8
*/
public IntStream ints() {
return StreamSupport.intStream
(new RandomIntsSpliterator
(0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number
* of pseudorandom {@code int} values, each conforming to the given
* origin (inclusive) and bound (exclusive).
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code int} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero, or {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public IntStream ints(long streamSize, int randomNumberOrigin,
int randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.intStream
(new RandomIntsSpliterator
(0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* int} values, each conforming to the given origin (inclusive) and bound
* (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code int} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.intStream
(new RandomIntsSpliterator
(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code long} values.
*
* @param streamSize the number of values to generate
* @return a stream of pseudorandom {@code long} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
* @since 1.8
*/
public LongStream longs(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.longStream
(new RandomLongsSpliterator
(0L, streamSize, Long.MAX_VALUE, 0L),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code long}
* values.
*
* @implNote This method is implemented to be equivalent to {@code
* longs(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code long} values
* @since 1.8
*/
public LongStream longs() {
return StreamSupport.longStream
(new RandomLongsSpliterator
(0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code long}, each conforming to the given origin
* (inclusive) and bound (exclusive).
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code long} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero, or {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public LongStream longs(long streamSize, long randomNumberOrigin,
long randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.longStream
(new RandomLongsSpliterator
(0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* long} values, each conforming to the given origin (inclusive) and bound
* (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code long} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
throw new IllegalArgumentException(BadRange);
return StreamSupport.longStream
(new RandomLongsSpliterator
(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code double} values, each between zero
* (inclusive) and one (exclusive).
*
* @param streamSize the number of values to generate
* @return a stream of {@code double} values
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
* @since 1.8
*/
public DoubleStream doubles(long streamSize) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(0L, streamSize, Double.MAX_VALUE, 0.0),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* double} values, each between zero (inclusive) and one
* (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* doubles(Long.MAX_VALUE)}.
*
* @return a stream of pseudorandom {@code double} values
* @since 1.8
*/
public DoubleStream doubles() {
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0),
false);
}
/**
* Returns a stream producing the given {@code streamSize} number of
* pseudorandom {@code double} values, each conforming to the given origin
* (inclusive) and bound (exclusive).
*
* @param streamSize the number of values to generate
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code streamSize} is
* less than zero
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public DoubleStream doubles(long streamSize, double randomNumberOrigin,
double randomNumberBound) {
if (streamSize < 0L)
throw new IllegalArgumentException(BadSize);
if (!(randomNumberOrigin < randomNumberBound))
throw new IllegalArgumentException(BadRange);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(0L, streamSize, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Returns an effectively unlimited stream of pseudorandom {@code
* double} values, each conforming to the given origin (inclusive) and bound
* (exclusive).
*
* @implNote This method is implemented to be equivalent to {@code
* doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}.
*
* @param randomNumberOrigin the origin (inclusive) of each random value
* @param randomNumberBound the bound (exclusive) of each random value
* @return a stream of pseudorandom {@code double} values,
* each with the given origin (inclusive) and bound (exclusive)
* @throws IllegalArgumentException if {@code randomNumberOrigin}
* is greater than or equal to {@code randomNumberBound}
* @since 1.8
*/
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
if (!(randomNumberOrigin < randomNumberBound))
throw new IllegalArgumentException(BadRange);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
false);
}
/**
* Spliterator for int streams. We multiplex the four int
* versions into one class by treating a bound less than origin as
* unbounded, and also by treating "infinite" as equivalent to
* Long.MAX_VALUE. For splits, it uses the standard divide-by-two
* approach. The long and double versions of this class are
* identical except for types.
*/
static final class RandomIntsSpliterator implements Spliterator.OfInt {
long index;
final long fence;
final int origin;
final int bound;
RandomIntsSpliterator(long index, long fence,
int origin, int bound) {
this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomIntsSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomIntsSpliterator(i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(IntConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(ThreadLocalRandom.current().internalNextInt(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(IntConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
int o = origin, b = bound;
ThreadLocalRandom rng = ThreadLocalRandom.current();
do {
consumer.accept(rng.internalNextInt(o, b));
} while (++i < f);
}
}
}
/**
* Spliterator for long streams.
*/
static final class RandomLongsSpliterator implements Spliterator.OfLong {
long index;
final long fence;
final long origin;
final long bound;
RandomLongsSpliterator(long index, long fence,
long origin, long bound) {
this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomLongsSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomLongsSpliterator(i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(LongConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(ThreadLocalRandom.current().internalNextLong(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(LongConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
long o = origin, b = bound;
ThreadLocalRandom rng = ThreadLocalRandom.current();
do {
consumer.accept(rng.internalNextLong(o, b));
} while (++i < f);
}
}
}
/**
* Spliterator for double streams.
*/
static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
long index;
final long fence;
final double origin;
final double bound;
RandomDoublesSpliterator(long index, long fence,
double origin, double bound) {
this.index = index; this.fence = fence;
this.origin = origin; this.bound = bound;
}
public RandomDoublesSpliterator trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomDoublesSpliterator(i, index = m, origin, bound);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
public boolean tryAdvance(DoubleConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(ThreadLocalRandom.current().internalNextDouble(origin, bound));
index = i + 1;
return true;
}
return false;
}
public void forEachRemaining(DoubleConsumer consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
index = f;
double o = origin, b = bound;
ThreadLocalRandom rng = ThreadLocalRandom.current();
do {
consumer.accept(rng.internalNextDouble(o, b));
} while (++i < f);
}
}
}
// Within-package utilities
/*
......@@ -401,23 +1009,26 @@ public class ThreadLocalRandom extends Random {
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("rnd", long.class),
new ObjectStreamField("initialized", boolean.class)
new ObjectStreamField("initialized", boolean.class),
};
/**
* Saves the {@code ThreadLocalRandom} to a stream (that is, serializes it).
* @param s the stream
* @throws java.io.IOException if an I/O error occurs
*/
private void writeObject(java.io.ObjectOutputStream out)
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
java.io.ObjectOutputStream.PutField fields = out.putFields();
java.io.ObjectOutputStream.PutField fields = s.putFields();
fields.put("rnd", UNSAFE.getLong(Thread.currentThread(), SEED));
fields.put("initialized", true);
out.writeFields();
s.writeFields();
}
/**
* Returns the {@link #current() current} thread's {@code ThreadLocalRandom}.
* @return the {@link #current() current} thread's {@code ThreadLocalRandom}
*/
private Object readResolve() {
return current();
......
......@@ -226,7 +226,11 @@ public class StampedLock implements java.io.Serializable {
* incoming reader arrives while read lock is held but there is a
* queued writer, this incoming reader is queued. (This rule is
* responsible for some of the complexity of method acquireRead,
* but without it, the lock becomes highly unfair.)
* but without it, the lock becomes highly unfair.) Method release
* does not (and sometimes cannot) itself wake up cowaiters. This
* is done by the primary thread, but helped by any other threads
* with nothing better to do in methods acquireRead and
* acquireWrite.
*
* These rules apply to threads actually queued. All tryLock forms
* opportunistically try to acquire locks regardless of preference
......@@ -267,11 +271,14 @@ public class StampedLock implements java.io.Serializable {
/** Number of processors, for spin control */
private static final int NCPU = Runtime.getRuntime().availableProcessors();
/** Maximum number of retries before blocking on acquisition */
/** Maximum number of retries before enqueuing on acquisition */
private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
/** Maximum number of retries before blocking at head on acquisition */
private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0;
/** Maximum number of retries before re-blocking */
private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 12 : 0;
private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0;
/** The period for yielding when waiting for overflow spinlock */
private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
......@@ -415,8 +422,8 @@ public class StampedLock implements java.io.Serializable {
* @return a stamp that can be used to unlock or convert mode
*/
public long readLock() {
long s, next; // bypass acquireRead on fully unlocked case only
return ((((s = state) & ABITS) == 0L &&
long s = state, next; // bypass acquireRead on common uncontended case
return ((whead == wtail && (s & ABITS) < RFULL &&
U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
next : acquireRead(false, 0L));
}
......@@ -1012,18 +1019,9 @@ public class StampedLock implements java.io.Serializable {
if (t.status <= 0)
q = t;
}
if (q != null) {
for (WNode r = q;;) { // release co-waiters too
if ((w = r.thread) != null) {
r.thread = null;
if (q != null && (w = q.thread) != null)
U.unpark(w);
}
if ((r = q.cowait) == null)
break;
U.compareAndSwapObject(q, WCOWAIT, r, r.cowait);
}
}
}
}
/**
......@@ -1038,22 +1036,22 @@ public class StampedLock implements java.io.Serializable {
private long acquireWrite(boolean interruptible, long deadline) {
WNode node = null, p;
for (int spins = -1;;) { // spin while enqueuing
long s, ns;
if (((s = state) & ABITS) == 0L) {
long m, s, ns;
if ((m = (s = state) & ABITS) == 0L) {
if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
return ns;
}
else if (spins < 0)
spins = (m == WBIT && wtail == whead) ? SPINS : 0;
else if (spins > 0) {
if (LockSupport.nextSecondarySeed() >= 0)
--spins;
}
else if ((p = wtail) == null) { // initialize queue
WNode h = new WNode(WMODE, null);
if (U.compareAndSwapObject(this, WHEAD, null, h))
wtail = h;
WNode hd = new WNode(WMODE, null);
if (U.compareAndSwapObject(this, WHEAD, null, hd))
wtail = hd;
}
else if (spins < 0)
spins = (p == whead) ? SPINS : 0;
else if (node == null)
node = new WNode(WMODE, p);
else if (node.prev != p)
......@@ -1064,14 +1062,18 @@ public class StampedLock implements java.io.Serializable {
}
}
for (int spins = SPINS;;) {
WNode np, pp; int ps; long s, ns; Thread w;
while ((np = node.prev) != p && np != null)
(p = np).next = node; // stale
if (whead == p) {
for (int spins = -1;;) {
WNode h, np, pp; int ps;
if ((h = whead) == p) {
if (spins < 0)
spins = HEAD_SPINS;
else if (spins < MAX_HEAD_SPINS)
spins <<= 1;
for (int k = spins;;) { // spin at head
long s, ns;
if (((s = state) & ABITS) == 0L) {
if (U.compareAndSwapLong(this, STATE, s, ns = s+WBIT)) {
if (U.compareAndSwapLong(this, STATE, s,
ns = s + WBIT)) {
whead = node;
node.prev = null;
return ns;
......@@ -1081,10 +1083,21 @@ public class StampedLock implements java.io.Serializable {
--k <= 0)
break;
}
if (spins < MAX_HEAD_SPINS)
spins <<= 1;
}
if ((ps = p.status) == 0)
else if (h != null) { // help release stale waiters
WNode c; Thread w;
while ((c = h.cowait) != null) {
if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
(w = c.thread) != null)
U.unpark(w);
}
}
if (whead == h) {
if ((np = node.prev) != p) {
if (np != null)
(p = np).next = node; // stale
}
else if ((ps = p.status) == 0)
U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
else if (ps == CANCELLED) {
if ((pp = p.prev) != null) {
......@@ -1099,11 +1112,11 @@ public class StampedLock implements java.io.Serializable {
else if ((time = deadline - System.nanoTime()) <= 0L)
return cancelWaiter(node, node, false);
Thread wt = Thread.currentThread();
U.putObject(wt, PARKBLOCKER, this); // emulate LockSupport.park
U.putObject(wt, PARKBLOCKER, this);
node.thread = wt;
if (node.prev == p && p.status == WAITING && // recheck
(p != whead || (state & ABITS) != 0L))
U.park(false, time);
if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&
whead == h && node.prev == p)
U.park(false, time); // emulate LockSupport.park
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
if (interruptible && Thread.interrupted())
......@@ -1111,6 +1124,7 @@ public class StampedLock implements java.io.Serializable {
}
}
}
}
/**
* See above for explanation.
......@@ -1122,115 +1136,134 @@ public class StampedLock implements java.io.Serializable {
* @return next state, or INTERRUPTED
*/
private long acquireRead(boolean interruptible, long deadline) {
WNode node = null, group = null, p;
WNode node = null, p;
for (int spins = -1;;) {
for (;;) {
long s, m, ns; WNode h, q; Thread w; // anti-barging guard
if (group == null && (h = whead) != null &&
(q = h.next) != null && q.mode != RMODE)
break;
WNode h;
if ((h = whead) == (p = wtail)) {
for (long m, s, ns;;) {
if ((m = (s = state) & ABITS) < RFULL ?
U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
(m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
if (group != null) { // help release others
for (WNode r = group;;) {
if ((w = r.thread) != null) {
r.thread = null;
U.unpark(w);
(m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L))
return ns;
else if (m >= WBIT) {
if (spins > 0) {
if (LockSupport.nextSecondarySeed() >= 0)
--spins;
}
if ((r = group.cowait) == null)
else {
if (spins == 0) {
WNode nh = whead, np = wtail;
if ((nh == h && np == p) || (h = nh) != (p = np))
break;
U.compareAndSwapObject(group, WCOWAIT, r, r.cowait);
}
spins = SPINS;
}
return ns;
}
if (m >= WBIT)
break;
}
if (spins > 0) {
if (LockSupport.nextSecondarySeed() >= 0)
--spins;
}
else if ((p = wtail) == null) {
WNode h = new WNode(WMODE, null);
if (U.compareAndSwapObject(this, WHEAD, null, h))
wtail = h;
if (p == null) { // initialize queue
WNode hd = new WNode(WMODE, null);
if (U.compareAndSwapObject(this, WHEAD, null, hd))
wtail = hd;
}
else if (spins < 0)
spins = (p == whead) ? SPINS : 0;
else if (node == null)
node = new WNode(WMODE, p);
else if (node.prev != p)
node = new WNode(RMODE, p);
else if (h == p || p.mode != RMODE) {
if (node.prev != p)
node.prev = p;
else if (p.mode == RMODE && p != whead) {
WNode pp = p.prev; // become co-waiter with group p
if (pp != null && p == wtail &&
U.compareAndSwapObject(p, WCOWAIT,
node.cowait = p.cowait, node)) {
node.thread = Thread.currentThread();
for (long time;;) {
else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
p.next = node;
break;
}
}
else if (!U.compareAndSwapObject(p, WCOWAIT,
node.cowait = p.cowait, node))
node.cowait = null;
else {
for (;;) {
WNode pp, c; Thread w;
if ((h = whead) != null && (c = h.cowait) != null &&
U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
(w = c.thread) != null) // help release
U.unpark(w);
if (h == (pp = p.prev) || h == p || pp == null) {
long m, s, ns;
do {
if ((m = (s = state) & ABITS) < RFULL ?
U.compareAndSwapLong(this, STATE, s,
ns = s + RUNIT) :
(m < WBIT &&
(ns = tryIncReaderOverflow(s)) != 0L))
return ns;
} while (m < WBIT);
}
if (whead == h && p.prev == pp) {
long time;
if (pp == null || h == p || p.status > 0) {
node = null; // throw away
break;
}
if (deadline == 0L)
time = 0L;
else if ((time = deadline - System.nanoTime()) <= 0L)
return cancelWaiter(node, p, false);
if (node.thread == null)
break;
if (p.prev != pp || p.status == CANCELLED ||
p == whead || p.prev != pp) {
node.thread = null;
break;
}
Thread wt = Thread.currentThread();
U.putObject(wt, PARKBLOCKER, this);
if (node.thread == null) // must recheck
break;
node.thread = wt;
if ((h != pp || (state & ABITS) == WBIT) &&
whead == h && p.prev == pp)
U.park(false, time);
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
if (interruptible && Thread.interrupted())
return cancelWaiter(node, p, true);
}
group = p;
}
node = null; // throw away
}
else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
p.next = node;
break;
}
}
for (int spins = SPINS;;) {
WNode np, pp, r; int ps; long m, s, ns; Thread w;
while ((np = node.prev) != p && np != null)
(p = np).next = node;
if (whead == p) {
for (int k = spins;;) {
if ((m = (s = state) & ABITS) != WBIT) {
if (m < RFULL ?
U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT):
(ns = tryIncReaderOverflow(s)) != 0L) {
for (int spins = -1;;) {
WNode h, np, pp; int ps;
if ((h = whead) == p) {
if (spins < 0)
spins = HEAD_SPINS;
else if (spins < MAX_HEAD_SPINS)
spins <<= 1;
for (int k = spins;;) { // spin at head
long m, s, ns;
if ((m = (s = state) & ABITS) < RFULL ?
U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
(m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
WNode c; Thread w;
whead = node;
node.prev = null;
while ((r = node.cowait) != null) {
while ((c = node.cowait) != null) {
if (U.compareAndSwapObject(node, WCOWAIT,
r, r.cowait) &&
(w = r.thread) != null) {
r.thread = null;
U.unpark(w); // release co-waiter
}
c, c.cowait) &&
(w = c.thread) != null)
U.unpark(w);
}
return ns;
}
}
else if (LockSupport.nextSecondarySeed() >= 0 &&
--k <= 0)
else if (m >= WBIT &&
LockSupport.nextSecondarySeed() >= 0 && --k <= 0)
break;
}
if (spins < MAX_HEAD_SPINS)
spins <<= 1;
}
if ((ps = p.status) == 0)
else if (h != null) {
WNode c; Thread w;
while ((c = h.cowait) != null) {
if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
(w = c.thread) != null)
U.unpark(w);
}
}
if (whead == h) {
if ((np = node.prev) != p) {
if (np != null)
(p = np).next = node; // stale
}
else if ((ps = p.status) == 0)
U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
else if (ps == CANCELLED) {
if ((pp = p.prev) != null) {
......@@ -1247,8 +1280,9 @@ public class StampedLock implements java.io.Serializable {
Thread wt = Thread.currentThread();
U.putObject(wt, PARKBLOCKER, this);
node.thread = wt;
if (node.prev == p && p.status == WAITING &&
(p != whead || (state & ABITS) != WBIT))
if (p.status < 0 &&
(p != h || (state & ABITS) == WBIT) &&
whead == h && node.prev == p)
U.park(false, time);
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
......@@ -1257,6 +1291,7 @@ public class StampedLock implements java.io.Serializable {
}
}
}
}
/**
* If node non-null, forces cancel status and unsplices it from
......@@ -1278,22 +1313,19 @@ public class StampedLock implements java.io.Serializable {
if (node != null && group != null) {
Thread w;
node.status = CANCELLED;
node.thread = null;
// unsplice cancelled nodes from group
for (WNode p = group, q; (q = p.cowait) != null;) {
if (q.status == CANCELLED)
U.compareAndSwapObject(p, WNEXT, q, q.next);
if (q.status == CANCELLED) {
U.compareAndSwapObject(p, WCOWAIT, q, q.cowait);
p = group; // restart
}
else
p = q;
}
if (group == node) {
WNode r; // detach and wake up uncancelled co-waiters
while ((r = node.cowait) != null) {
if (U.compareAndSwapObject(node, WCOWAIT, r, r.cowait) &&
(w = r.thread) != null) {
r.thread = null;
U.unpark(w);
}
for (WNode r = group.cowait; r != null; r = r.cowait) {
if ((w = r.thread) != null)
U.unpark(w); // wake up uncancelled co-waiters
}
for (WNode pred = node.prev; pred != null; ) { // unsplice
WNode succ, pp; // find valid successor
......
......@@ -32,6 +32,7 @@ import java.security.*;
import java.security.cert.CertificateException;
import java.util.zip.ZipEntry;
import sun.misc.JarIndex;
import sun.security.util.ManifestDigester;
import sun.security.util.ManifestEntryVerifier;
import sun.security.util.SignatureFileVerifier;
......@@ -139,7 +140,8 @@ class JarVerifier {
return;
}
if (uname.equals(JarFile.MANIFEST_NAME)) {
if (uname.equals(JarFile.MANIFEST_NAME) ||
uname.equals(JarIndex.INDEX_NAME)) {
return;
}
......
......@@ -457,13 +457,15 @@ public class Logger {
* of the subsystem, such as java.net
* or javax.swing
* @param resourceBundleName name of ResourceBundle to be used for localizing
* messages for this logger. May be <CODE>null</CODE> if none of
* the messages require localization.
* messages for this logger. May be {@code null}
* if none of the messages require localization.
* @return a suitable Logger
* @throws MissingResourceException if the resourceBundleName is non-null and
* no corresponding resource can be found.
* @throws IllegalArgumentException if the Logger already exists and uses
* a different resource bundle name.
* a different resource bundle name; or if
* {@code resourceBundleName} is {@code null} but the named
* logger has a resource bundle set.
* @throws NullPointerException if the name is null.
*/
......@@ -1731,10 +1733,6 @@ public class Logger {
// Synchronized to prevent races in setting the fields.
private synchronized void setupResourceInfo(String name,
Class<?> callersClass) {
if (name == null) {
return;
}
if (resourceBundleName != null) {
// this Logger already has a ResourceBundle
......@@ -1748,6 +1746,10 @@ public class Logger {
resourceBundleName + " != " + name);
}
if (name == null) {
return;
}
setCallersClassLoaderRef(callersClass);
if (findResourceBundle(name, true) == null) {
// We've failed to find an expected ResourceBundle.
......
......@@ -219,7 +219,7 @@ import java.util.stream.StreamSupport;
*
* <tr><th>&nbsp;</th></tr>
* <tr align="left"><th colspan="2" id="unicode">Classes for Unicode scripts, blocks, categories and binary properties</th></tr>
* * <tr><td valign="top" headers="construct unicode">{@code \p{IsLatin}}</td>
* <tr><td valign="top" headers="construct unicode">{@code \p{IsLatin}}</td>
* <td headers="matches">A Latin&nbsp;script character (<a href="#usc">script</a>)</td></tr>
* <tr><td valign="top" headers="construct unicode">{@code \p{InGreek}}</td>
* <td headers="matches">A character in the Greek&nbsp;block (<a href="#ubc">block</a>)</td></tr>
......@@ -4456,16 +4456,16 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
groups[groupIndex+1] = i;
groups[groupIndex] = i - k;
}
i = i - k;
return true;
}
// backing off
i = i - k;
if (capture) {
groups[groupIndex+1] = i;
groups[groupIndex] = i - k;
}
i = i - k;
j--;
}
break;
}
......@@ -4883,7 +4883,6 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
int k = matcher.groups[groupIndex+1];
int groupSize = k - j;
// If the referenced group didn't match, neither can this
if (j < 0)
return false;
......@@ -4893,7 +4892,6 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
matcher.hitEnd = true;
return false;
}
// Check each new char to make sure it matches what the group
// referenced matched last time around
for (int index=0; index<groupSize; index++)
......
......@@ -137,6 +137,11 @@ public final class Collectors {
return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
}
@SuppressWarnings("unchecked")
private static <I, R> Function<I, R> castingIdentity() {
return i -> (R) i;
}
/**
* Simple implementation class for {@code Collector}.
*
......@@ -166,7 +171,7 @@ public final class Collectors {
BiConsumer<A, T> accumulator,
BinaryOperator<A> combiner,
Set<Characteristics> characteristics) {
this(supplier, accumulator, combiner, i -> (R) i, characteristics);
this(supplier, accumulator, combiner, castingIdentity(), characteristics);
}
@Override
......@@ -209,7 +214,7 @@ public final class Collectors {
*/
public static <T, C extends Collection<T>>
Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
return new CollectorImpl<>(collectionFactory, Collection::add,
return new CollectorImpl<>(collectionFactory, Collection<T>::add,
(r1, r2) -> { r1.addAll(r2); return r1; },
CH_ID);
}
......@@ -1046,30 +1051,23 @@ public final class Collectors {
public static <T, D, A>
Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
Collector<? super T, A, D> downstream) {
@SuppressWarnings("unchecked")
BiConsumer<D, ? super T> downstreamAccumulator = (BiConsumer<D, ? super T>) downstream.accumulator();
BiConsumer<Map<Boolean, A>, T> accumulator = (result, t) -> {
Partition<D> asPartition = ((Partition<D>) result);
downstreamAccumulator.accept(predicate.test(t) ? asPartition.forTrue : asPartition.forFalse, t);
};
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
BiConsumer<Partition<A>, T> accumulator = (result, t) ->
downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t);
BinaryOperator<A> op = downstream.combiner();
BinaryOperator<Map<Boolean, A>> merger = (m1, m2) -> {
Partition<A> left = (Partition<A>) m1;
Partition<A> right = (Partition<A>) m2;
return new Partition<>(op.apply(left.forTrue, right.forTrue),
BinaryOperator<Partition<A>> merger = (left, right) ->
new Partition<>(op.apply(left.forTrue, right.forTrue),
op.apply(left.forFalse, right.forFalse));
};
Supplier<Map<Boolean, A>> supplier = () -> new Partition<>(downstream.supplier().get(),
Supplier<Partition<A>> supplier = () ->
new Partition<>(downstream.supplier().get(),
downstream.supplier().get());
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
}
else {
Function<Map<Boolean, A>, Map<Boolean, D>> finisher = (Map<Boolean, A> par) -> {
Partition<A> asAPartition = (Partition<A>) par;
return new Partition<>(downstream.finisher().apply(asAPartition.forTrue),
downstream.finisher().apply(asAPartition.forFalse));
};
Function<Partition<A>, Map<Boolean, D>> finisher = par ->
new Partition<>(downstream.finisher().apply(par.forTrue),
downstream.finisher().apply(par.forFalse));
return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
}
}
......
......@@ -101,7 +101,7 @@ final class DistinctOps {
if (StreamOpFlag.DISTINCT.isKnown(flags)) {
return sink;
} else if (StreamOpFlag.SORTED.isKnown(flags)) {
return new Sink.ChainedReference<T>(sink) {
return new Sink.ChainedReference<T, T>(sink) {
boolean seenNull;
T lastSeen;
......@@ -132,7 +132,7 @@ final class DistinctOps {
}
};
} else {
return new Sink.ChainedReference<T>(sink) {
return new Sink.ChainedReference<T, T>(sink) {
Set<T> seen;
@Override
......
......@@ -191,7 +191,7 @@ abstract class DoublePipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble(sink) {
return new Sink.ChainedDouble<Double>(sink) {
@Override
public void accept(double t) {
downstream.accept(mapper.applyAsDouble(t));
......@@ -208,9 +208,8 @@ abstract class DoublePipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Double> opWrapSink(int flags, Sink<U> sink) {
return new Sink.ChainedDouble(sink) {
return new Sink.ChainedDouble<U>(sink) {
@Override
@SuppressWarnings("unchecked")
public void accept(double t) {
downstream.accept(mapper.apply(t));
}
......@@ -226,7 +225,7 @@ abstract class DoublePipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedDouble(sink) {
return new Sink.ChainedDouble<Integer>(sink) {
@Override
public void accept(double t) {
downstream.accept(mapper.applyAsInt(t));
......@@ -243,7 +242,7 @@ abstract class DoublePipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedDouble(sink) {
return new Sink.ChainedDouble<Long>(sink) {
@Override
public void accept(double t) {
downstream.accept(mapper.applyAsLong(t));
......@@ -259,7 +258,7 @@ abstract class DoublePipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble(sink) {
return new Sink.ChainedDouble<Double>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
......@@ -296,7 +295,7 @@ abstract class DoublePipeline<E_IN>
StreamOpFlag.NOT_SIZED) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble(sink) {
return new Sink.ChainedDouble<Double>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
......@@ -319,7 +318,7 @@ abstract class DoublePipeline<E_IN>
0) {
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble(sink) {
return new Sink.ChainedDouble<Double>(sink) {
@Override
public void accept(double t) {
consumer.accept(t);
......
......@@ -189,9 +189,8 @@ abstract class IntPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedInt(sink) {
return new Sink.ChainedInt<Long>(sink) {
@Override
@SuppressWarnings("unchecked")
public void accept(int t) {
downstream.accept((long) t);
}
......@@ -206,9 +205,8 @@ abstract class IntPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedInt(sink) {
return new Sink.ChainedInt<Double>(sink) {
@Override
@SuppressWarnings("unchecked")
public void accept(int t) {
downstream.accept((double) t);
}
......@@ -229,7 +227,7 @@ abstract class IntPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedInt(sink) {
return new Sink.ChainedInt<Integer>(sink) {
@Override
public void accept(int t) {
downstream.accept(mapper.applyAsInt(t));
......@@ -246,9 +244,8 @@ abstract class IntPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<U> sink) {
return new Sink.ChainedInt(sink) {
return new Sink.ChainedInt<U>(sink) {
@Override
@SuppressWarnings("unchecked")
public void accept(int t) {
downstream.accept(mapper.apply(t));
}
......@@ -264,7 +261,7 @@ abstract class IntPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedInt(sink) {
return new Sink.ChainedInt<Long>(sink) {
@Override
public void accept(int t) {
downstream.accept(mapper.applyAsLong(t));
......@@ -281,7 +278,7 @@ abstract class IntPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedInt(sink) {
return new Sink.ChainedInt<Double>(sink) {
@Override
public void accept(int t) {
downstream.accept(mapper.applyAsDouble(t));
......@@ -297,7 +294,7 @@ abstract class IntPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedInt(sink) {
return new Sink.ChainedInt<Integer>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
......@@ -334,7 +331,7 @@ abstract class IntPipeline<E_IN>
StreamOpFlag.NOT_SIZED) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedInt(sink) {
return new Sink.ChainedInt<Integer>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
......@@ -357,7 +354,7 @@ abstract class IntPipeline<E_IN>
0) {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedInt(sink) {
return new Sink.ChainedInt<Integer>(sink) {
@Override
public void accept(int t) {
consumer.accept(t);
......
......@@ -186,7 +186,7 @@ abstract class LongPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Long> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedLong(sink) {
return new Sink.ChainedLong<Double>(sink) {
@Override
public void accept(long t) {
downstream.accept((double) t);
......@@ -208,9 +208,8 @@ abstract class LongPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedLong(sink) {
return new Sink.ChainedLong<Long>(sink) {
@Override
@SuppressWarnings("unchecked")
public void accept(long t) {
downstream.accept(mapper.applyAsLong(t));
}
......@@ -226,9 +225,8 @@ abstract class LongPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Long> opWrapSink(int flags, Sink<U> sink) {
return new Sink.ChainedLong(sink) {
return new Sink.ChainedLong<U>(sink) {
@Override
@SuppressWarnings("unchecked")
public void accept(long t) {
downstream.accept(mapper.apply(t));
}
......@@ -244,9 +242,8 @@ abstract class LongPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Long> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedLong(sink) {
return new Sink.ChainedLong<Integer>(sink) {
@Override
@SuppressWarnings("unchecked")
public void accept(long t) {
downstream.accept(mapper.applyAsInt(t));
}
......@@ -262,7 +259,7 @@ abstract class LongPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<Long> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedLong(sink) {
return new Sink.ChainedLong<Double>(sink) {
@Override
public void accept(long t) {
downstream.accept(mapper.applyAsDouble(t));
......@@ -278,7 +275,7 @@ abstract class LongPipeline<E_IN>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedLong(sink) {
return new Sink.ChainedLong<Long>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
......@@ -315,7 +312,7 @@ abstract class LongPipeline<E_IN>
StreamOpFlag.NOT_SIZED) {
@Override
Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedLong(sink) {
return new Sink.ChainedLong<Long>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
......@@ -338,7 +335,7 @@ abstract class LongPipeline<E_IN>
0) {
@Override
Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedLong(sink) {
return new Sink.ChainedLong<Long>(sink) {
@Override
public void accept(long t) {
consumer.accept(t);
......
......@@ -163,17 +163,16 @@ abstract class ReferencePipeline<P_IN, P_OUT>
StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
return new Sink.ChainedReference<P_OUT>(sink) {
return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
}
@Override
@SuppressWarnings("unchecked")
public void accept(P_OUT u) {
if (predicate.test(u))
downstream.accept((Object) u);
downstream.accept(u);
}
};
}
......@@ -188,7 +187,7 @@ abstract class ReferencePipeline<P_IN, P_OUT>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT>(sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.apply(u));
......@@ -205,7 +204,7 @@ abstract class ReferencePipeline<P_IN, P_OUT>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedReference<P_OUT>(sink) {
return new Sink.ChainedReference<P_OUT, Integer>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.applyAsInt(u));
......@@ -222,7 +221,7 @@ abstract class ReferencePipeline<P_IN, P_OUT>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedReference<P_OUT>(sink) {
return new Sink.ChainedReference<P_OUT, Long>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.applyAsLong(u));
......@@ -239,7 +238,7 @@ abstract class ReferencePipeline<P_IN, P_OUT>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedReference<P_OUT>(sink) {
return new Sink.ChainedReference<P_OUT, Double>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.applyAsDouble(u));
......@@ -257,14 +256,13 @@ abstract class ReferencePipeline<P_IN, P_OUT>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT>(sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
@Override
public void begin(long size) {
downstream.begin(-1);
}
@Override
@SuppressWarnings("unchecked")
public void accept(P_OUT u) {
// We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
Stream<? extends R> result = mapper.apply(u);
......@@ -284,7 +282,7 @@ abstract class ReferencePipeline<P_IN, P_OUT>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedReference<P_OUT>(sink) {
return new Sink.ChainedReference<P_OUT, Integer>(sink) {
IntConsumer downstreamAsInt = downstream::accept;
@Override
public void begin(long size) {
......@@ -311,7 +309,7 @@ abstract class ReferencePipeline<P_IN, P_OUT>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedReference<P_OUT>(sink) {
return new Sink.ChainedReference<P_OUT, Double>(sink) {
DoubleConsumer downstreamAsDouble = downstream::accept;
@Override
public void begin(long size) {
......@@ -338,7 +336,7 @@ abstract class ReferencePipeline<P_IN, P_OUT>
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedReference<P_OUT>(sink) {
return new Sink.ChainedReference<P_OUT, Long>(sink) {
LongConsumer downstreamAsLong = downstream::accept;
@Override
public void begin(long size) {
......@@ -364,9 +362,8 @@ abstract class ReferencePipeline<P_IN, P_OUT>
0) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
return new Sink.ChainedReference<P_OUT>(sink) {
return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
@Override
@SuppressWarnings("unchecked")
public void accept(P_OUT u) {
tee.accept(u);
downstream.accept(u);
......@@ -495,6 +492,7 @@ abstract class ReferencePipeline<P_IN, P_OUT>
}
@Override
@SuppressWarnings("unchecked")
public final <R, A> R collect(Collector<? super P_OUT, A, ? extends R> collector) {
A container;
if (isParallel()
......
......@@ -241,11 +241,10 @@ interface Sink<T> extends Consumer<T> {
* implementation of the {@code accept()} method must call the correct
* {@code accept()} method on the downstream {@code Sink}.
*/
static abstract class ChainedReference<T> implements Sink<T> {
@SuppressWarnings("rawtypes")
protected final Sink downstream;
static abstract class ChainedReference<T, E_OUT> implements Sink<T> {
protected final Sink<? super E_OUT> downstream;
public ChainedReference(Sink downstream) {
public ChainedReference(Sink<? super E_OUT> downstream) {
this.downstream = Objects.requireNonNull(downstream);
}
......@@ -274,11 +273,10 @@ interface Sink<T> extends Consumer<T> {
* The implementation of the {@code accept()} method must call the correct
* {@code accept()} method on the downstream {@code Sink}.
*/
static abstract class ChainedInt implements Sink.OfInt {
@SuppressWarnings("rawtypes")
protected final Sink downstream;
static abstract class ChainedInt<E_OUT> implements Sink.OfInt {
protected final Sink<? super E_OUT> downstream;
public ChainedInt(Sink downstream) {
public ChainedInt(Sink<? super E_OUT> downstream) {
this.downstream = Objects.requireNonNull(downstream);
}
......@@ -307,11 +305,10 @@ interface Sink<T> extends Consumer<T> {
* The implementation of the {@code accept()} method must call the correct
* {@code accept()} method on the downstream {@code Sink}.
*/
static abstract class ChainedLong implements Sink.OfLong {
@SuppressWarnings("rawtypes")
protected final Sink downstream;
static abstract class ChainedLong<E_OUT> implements Sink.OfLong {
protected final Sink<? super E_OUT> downstream;
public ChainedLong(Sink downstream) {
public ChainedLong(Sink<? super E_OUT> downstream) {
this.downstream = Objects.requireNonNull(downstream);
}
......@@ -340,11 +337,10 @@ interface Sink<T> extends Consumer<T> {
* The implementation of the {@code accept()} method must call the correct
* {@code accept()} method on the downstream {@code Sink}.
*/
static abstract class ChainedDouble implements Sink.OfDouble {
@SuppressWarnings("rawtypes")
protected final Sink downstream;
static abstract class ChainedDouble<E_OUT> implements Sink.OfDouble {
protected final Sink<? super E_OUT> downstream;
public ChainedDouble(Sink downstream) {
public ChainedDouble(Sink<? super E_OUT> downstream) {
this.downstream = Objects.requireNonNull(downstream);
}
......
......@@ -96,6 +96,11 @@ final class SliceOps {
}
}
@SuppressWarnings("unchecked")
private static <T> IntFunction<T[]> castingArray() {
return size -> (T[]) new Object[size];
}
/**
* Appends a "slice" operation to the provided stream. The slice operation
* may be may be skip-only, limit-only, or skip-and-limit.
......@@ -111,7 +116,7 @@ final class SliceOps {
if (skip < 0)
throw new IllegalArgumentException("Skip must be non-negative: " + skip);
return new ReferencePipeline.StatefulOp<T,T>(upstream, StreamShape.REFERENCE,
return new ReferencePipeline.StatefulOp<T, T>(upstream, StreamShape.REFERENCE,
flags(limit)) {
Spliterator<T> unorderedSkipLimitSpliterator(Spliterator<T> s,
long skip, long limit, long sizeIfKnown) {
......@@ -146,7 +151,7 @@ final class SliceOps {
// cancellation will be more aggressive cancelling later tasks
// if the target slice size has been reached from a given task,
// cancellation should also clear local results if any
return new SliceTask<>(this, helper, spliterator, i -> (T[]) new Object[i], skip, limit).
return new SliceTask<>(this, helper, spliterator, castingArray(), skip, limit).
invoke().spliterator();
}
}
......@@ -182,7 +187,7 @@ final class SliceOps {
@Override
Sink<T> opWrapSink(int flags, Sink<T> sink) {
return new Sink.ChainedReference<T>(sink) {
return new Sink.ChainedReference<T, T>(sink) {
long n = skip;
long m = limit >= 0 ? limit : Long.MAX_VALUE;
......@@ -291,7 +296,7 @@ final class SliceOps {
@Override
Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedInt(sink) {
return new Sink.ChainedInt<Integer>(sink) {
long n = skip;
long m = limit >= 0 ? limit : Long.MAX_VALUE;
......@@ -400,7 +405,7 @@ final class SliceOps {
@Override
Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedLong(sink) {
return new Sink.ChainedLong<Long>(sink) {
long n = skip;
long m = limit >= 0 ? limit : Long.MAX_VALUE;
......@@ -509,7 +514,7 @@ final class SliceOps {
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble(sink) {
return new Sink.ChainedDouble<Double>(sink) {
long n = skip;
long m = limit >= 0 ? limit : Long.MAX_VALUE;
......@@ -560,13 +565,13 @@ final class SliceOps {
private volatile boolean completed;
SliceTask(AbstractPipeline<?, P_OUT, ?> op,
SliceTask(AbstractPipeline<P_OUT, P_OUT, ?> op,
PipelineHelper<P_OUT> helper,
Spliterator<P_IN> spliterator,
IntFunction<P_OUT[]> generator,
long offset, long size) {
super(helper, spliterator);
this.op = (AbstractPipeline<P_OUT, P_OUT, ?>) op;
this.op = op;
this.generator = generator;
this.targetOffset = offset;
this.targetSize = size;
......
......@@ -129,7 +129,7 @@ final class SortedOps {
}
@Override
public Sink<T> opWrapSink(int flags, Sink sink) {
public Sink<T> opWrapSink(int flags, Sink<T> sink) {
Objects.requireNonNull(sink);
// If the input is already naturally sorted and this operation
......@@ -280,12 +280,12 @@ final class SortedOps {
/**
* {@link ForkJoinTask} for implementing sort on SIZED reference streams.
*/
private static final class SizedRefSortingSink<T> extends Sink.ChainedReference<T> {
private static final class SizedRefSortingSink<T> extends Sink.ChainedReference<T, T> {
private final Comparator<? super T> comparator;
private T[] array;
private int offset;
SizedRefSortingSink(Sink<T> sink, Comparator<? super T> comparator) {
SizedRefSortingSink(Sink<? super T> sink, Comparator<? super T> comparator) {
super(sink);
this.comparator = comparator;
}
......@@ -320,11 +320,11 @@ final class SortedOps {
/**
* {@link Sink} for implementing sort on reference streams.
*/
private static final class RefSortingSink<T> extends Sink.ChainedReference<T> {
private static final class RefSortingSink<T> extends Sink.ChainedReference<T, T> {
private final Comparator<? super T> comparator;
private ArrayList<T> list;
RefSortingSink(Sink<T> sink, Comparator<? super T> comparator) {
RefSortingSink(Sink<? super T> sink, Comparator<? super T> comparator) {
super(sink);
this.comparator = comparator;
}
......@@ -352,11 +352,11 @@ final class SortedOps {
/**
* {@link Sink} for implementing sort on SIZED int streams.
*/
private static final class SizedIntSortingSink extends Sink.ChainedInt {
private static final class SizedIntSortingSink extends Sink.ChainedInt<Integer> {
private int[] array;
private int offset;
SizedIntSortingSink(Sink downstream) {
SizedIntSortingSink(Sink<? super Integer> downstream) {
super(downstream);
}
......@@ -386,10 +386,10 @@ final class SortedOps {
/**
* {@link Sink} for implementing sort on int streams.
*/
private static final class IntSortingSink extends Sink.ChainedInt {
private static final class IntSortingSink extends Sink.ChainedInt<Integer> {
private SpinedBuffer.OfInt b;
IntSortingSink(Sink sink) {
IntSortingSink(Sink<? super Integer> sink) {
super(sink);
}
......@@ -417,11 +417,11 @@ final class SortedOps {
/**
* {@link Sink} for implementing sort on SIZED long streams.
*/
private static final class SizedLongSortingSink extends Sink.ChainedLong {
private static final class SizedLongSortingSink extends Sink.ChainedLong<Long> {
private long[] array;
private int offset;
SizedLongSortingSink(Sink downstream) {
SizedLongSortingSink(Sink<? super Long> downstream) {
super(downstream);
}
......@@ -451,10 +451,10 @@ final class SortedOps {
/**
* {@link Sink} for implementing sort on long streams.
*/
private static final class LongSortingSink extends Sink.ChainedLong {
private static final class LongSortingSink extends Sink.ChainedLong<Long> {
private SpinedBuffer.OfLong b;
LongSortingSink(Sink sink) {
LongSortingSink(Sink<? super Long> sink) {
super(sink);
}
......@@ -482,11 +482,11 @@ final class SortedOps {
/**
* {@link Sink} for implementing sort on SIZED double streams.
*/
private static final class SizedDoubleSortingSink extends Sink.ChainedDouble {
private static final class SizedDoubleSortingSink extends Sink.ChainedDouble<Double> {
private double[] array;
private int offset;
SizedDoubleSortingSink(Sink downstream) {
SizedDoubleSortingSink(Sink<? super Double> downstream) {
super(downstream);
}
......@@ -516,10 +516,10 @@ final class SortedOps {
/**
* {@link Sink} for implementing sort on double streams.
*/
private static final class DoubleSortingSink extends Sink.ChainedDouble {
private static final class DoubleSortingSink extends Sink.ChainedDouble<Double> {
private SpinedBuffer.OfDouble b;
DoubleSortingSink(Sink sink) {
DoubleSortingSink(Sink<? super Double> sink) {
super(sink);
}
......
......@@ -663,6 +663,9 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
while (off + 4 <= len) {
int tag = get16(extra, off);
int sz = get16(extra, off + 2);
if (sz < 0 || (off + 4 + sz) > len) {
break;
}
if (tag == EXTID_EXTT || tag == EXTID_ZIP64) {
skipped += (sz + 4);
}
......@@ -684,11 +687,18 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
while (off + 4 <= len) {
int tag = get16(extra, off);
int sz = get16(extra, off + 2);
if (sz < 0 || (off + 4 + sz) > len) {
writeBytes(extra, off, len - off);
return;
}
if (tag != EXTID_EXTT && tag != EXTID_ZIP64) {
writeBytes(extra, off, sz + 4);
}
off += (sz + 4);
}
if (off < len) {
writeBytes(extra, off, len - off);
}
}
}
......
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -293,6 +293,7 @@ public final class SNIHostName extends SNIServerName {
* the <a href="{@docRoot}/java/util/regex/Pattern.html#sum">
* regular expression pattern</a>
* representing the hostname(s) to match
* @return a {@code SNIMatcher} object for {@code SNIHostName}s
* @throws NullPointerException if {@code regex} is
* {@code null}
* @throws java.util.regex.PatternSyntaxException if the regular expression's
......
/*
* Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -40,7 +40,7 @@ import java.net.Socket;
* <UL>
* <LI> determine the set of aliases that are available for negotiations
* based on the criteria presented,
* <LI> select the <ITALIC> best alias </ITALIC> based on
* <LI> select the <i> best alias</i> based on
* the criteria presented, and
* <LI> obtain the corresponding key material for given aliases.
* </UL>
......
......@@ -197,8 +197,7 @@ public final class KerberosPrincipal
* {@code KerberosPrincipal} and the two
* {@code KerberosPrincipal} instances are equivalent.
* More formally two {@code KerberosPrincipal} instances are equal
* if the values returned by {@code getName()} are equal and the
* values returned by {@code getNameType()} are equal.
* if the values returned by {@code getName()} are equal.
*
* @param other the Object to compare to
* @return true if the Object passed in represents the same principal
......@@ -211,15 +210,10 @@ public final class KerberosPrincipal
if (! (other instanceof KerberosPrincipal)) {
return false;
} else {
}
String myFullName = getName();
String otherFullName = ((KerberosPrincipal) other).getName();
if (nameType == ((KerberosPrincipal)other).nameType &&
myFullName.equals(otherFullName)) {
return true;
}
}
return false;
return myFullName.equals(otherFullName);
}
/**
......
......@@ -193,9 +193,4 @@ abstract class AbstractPollSelectorImpl
if (!selch.isOpen() && !selch.isRegistered())
((SelChImpl)selch).kill();
}
static {
Util.load();
}
}
......@@ -1138,7 +1138,7 @@ class DatagramChannelImpl
throws IOException;
static {
Util.load();
IOUtil.load();
initIDs();
}
......
......@@ -1162,7 +1162,7 @@ public class FileChannelImpl
private static native long initIDs();
static {
Util.load();
IOUtil.load();
allocationGranularity = initIDs();
}
......
......@@ -347,9 +347,23 @@ public class IOUtil {
static native void initIDs();
/**
* Used to trigger loading of native libraries
*/
public static void load() { }
static {
// Note that IOUtil.initIDs is called from within Util.load.
Util.load();
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
System.loadLibrary("net");
System.loadLibrary("nio");
return null;
}
});
initIDs();
IOV_MAX = iovMax();
}
......
......@@ -582,7 +582,7 @@ public class Net {
private static native void initIDs();
static {
Util.load();
IOUtil.load();
initIDs();
}
......
......@@ -416,7 +416,7 @@ class ServerSocketChannelImpl
private static native void initIDs();
static {
Util.load();
IOUtil.load();
initIDs();
nd = new SocketDispatcher();
}
......
......@@ -1024,7 +1024,7 @@ class SocketChannelImpl
throws IOException;
static {
Util.load();
IOUtil.load();
nd = new SocketDispatcher();
}
......
......@@ -401,30 +401,4 @@ public class Util {
return bugLevel.equals(bl);
}
// -- Initialization --
private static boolean loaded = false;
public static void load() {
synchronized (Util.class) {
if (loaded)
return;
loaded = true;
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
System.loadLibrary("net");
System.loadLibrary("nio");
return null;
}
});
// IOUtil must be initialized; Its native methods are called from
// other places in native nio code so they must be set up.
IOUtil.initIDs();
}
}
}
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -268,8 +268,13 @@ public class ConnectDialog extends InternalDialog
public void revalidate() {
// Adjust some colors
Color disabledForeground = UIManager.getColor("Label.disabledForeground");
if (disabledForeground == null) {
// fall back for Nimbus that doesn't support 'Label.disabledForeground'
disabledForeground = UIManager.getColor("Label.disabledText");
}
hintTextColor =
ensureContrast(UIManager.getColor("Label.disabledForeground"),
ensureContrast(disabledForeground,
UIManager.getColor("Panel.background"));
disabledTableCellColor =
ensureContrast(new Color(0x808080),
......
......@@ -858,6 +858,10 @@ public class JConsole extends JFrame
try {
updateInterval = Integer.parseInt(arg.substring(10)) *
1000;
if (updateInterval <= 0) {
usage();
return;
}
} catch (NumberFormatException ex) {
usage();
return;
......
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -146,7 +146,6 @@ final public class Messages {
public static String HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME;
public static String HELP_ABOUT_DIALOG_MASTHEAD_TITLE;
public static String HELP_ABOUT_DIALOG_TITLE;
public static String HELP_ABOUT_DIALOG_USER_GUIDE_LINK;
public static String HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL;
public static String HELP_MENU_ABOUT_TITLE;
public static String HELP_MENU_USER_GUIDE_TITLE;
......@@ -272,6 +271,7 @@ final public class Messages {
public static String THREADS;
public static String THREAD_TAB_THREAD_INFO_ACCESSIBLE_NAME;
public static String THREAD_TAB_THREAD_PLOTTER_ACCESSIBLE_NAME;
public static String THREAD_TAB_INITIAL_STACK_TRACE_MESSAGE;
public static String THRESHOLD;
public static String TILE;
public static String TIME_RANGE_COLON;
......
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -337,6 +337,13 @@ public class Plotter extends JComponent
public void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth()-rightMargin-leftMargin-10;
int height = getHeight()-topMargin-bottomMargin;
if (width <= 0 || height <= 0) {
// not enough room to paint anything
return;
}
Color oldColor = g.getColor();
Font oldFont = g.getFont();
Color fg = getForeground();
......
......@@ -595,6 +595,8 @@ class ThreadTab extends Tab implements ActionListener, DocumentListener, ListSel
setBorder(thinEmptyBorder);
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
textArea.setText(Messages.THREAD_TAB_INITIAL_STACK_TRACE_MESSAGE);
addListSelectionListener(ThreadTab.this);
setCellRenderer(new DefaultListCellRenderer() {
public Component getListCellRendererComponent(JList<?> list, Object value, int index,
......
......@@ -153,9 +153,11 @@ public class VMPanel extends JTabbedPane implements PropertyChangeListener {
// in order to reserve space for the connect toggle.
public void setUI(TabbedPaneUI ui) {
Insets insets = (Insets) UIManager.getLookAndFeelDefaults().get("TabbedPane.tabAreaInsets");
if (insets != null) {
insets = (Insets) insets.clone();
insets.right += connectedIcon24.getIconWidth() + 8;
UIManager.put("TabbedPane.tabAreaInsets", insets);
}
super.setUI(ui);
}
......
......@@ -104,7 +104,6 @@ HELP_ABOUT_DIALOG_JAVA_VERSION=Java VM version:<br>{0}
HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME=Masthead Graphic
HELP_ABOUT_DIALOG_MASTHEAD_TITLE=About JConsole
HELP_ABOUT_DIALOG_TITLE=JConsole: About
HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole &User Guide:<br>{0}
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
HELP_MENU_ABOUT_TITLE=&About JConsole
HELP_MENU_USER_GUIDE_TITLE=Online &User Guide
......@@ -230,6 +229,7 @@ SUMMARY_TAB_VM_VERSION={0} version {1}
THREADS=Threads
THREAD_TAB_THREAD_INFO_ACCESSIBLE_NAME=Thread Information
THREAD_TAB_THREAD_PLOTTER_ACCESSIBLE_NAME=Chart for number of threads.
THREAD_TAB_INITIAL_STACK_TRACE_MESSAGE=[No thread selected]
THRESHOLD=Threshold
TILE=&Tile
TIME_RANGE_COLON=&Time Range:
......
......@@ -104,7 +104,6 @@ HELP_ABOUT_DIALOG_JAVA_VERSION=Java VM\u30D0\u30FC\u30B8\u30E7\u30F3:<br>{0}
HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME=\u30DE\u30B9\u30C8\u30D8\u30C3\u30C9\u56F3\u5F62
HELP_ABOUT_DIALOG_MASTHEAD_TITLE=JConsole\u306B\u3064\u3044\u3066
HELP_ABOUT_DIALOG_TITLE=JConsole: \u8A73\u7D30
HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U):<br>{0}
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
HELP_MENU_ABOUT_TITLE=JConsole\u306B\u3064\u3044\u3066(&A)
HELP_MENU_USER_GUIDE_TITLE=\u30AA\u30F3\u30E9\u30A4\u30F3\u30FB\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U)
......
......@@ -104,7 +104,6 @@ HELP_ABOUT_DIALOG_JAVA_VERSION=Java VM \u7248\u672C:<br>{0}
HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME=\u62A5\u5934\u56FE
HELP_ABOUT_DIALOG_MASTHEAD_TITLE=\u5173\u4E8E JConsole
HELP_ABOUT_DIALOG_TITLE=JConsole: \u5173\u4E8E
HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole \u7528\u6237\u6307\u5357(&U):<br>{0}
HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html
HELP_MENU_ABOUT_TITLE=\u5173\u4E8E JConsole(&A)
HELP_MENU_USER_GUIDE_TITLE=\u8054\u673A\u7528\u6237\u6307\u5357(&U)
......
......@@ -181,6 +181,7 @@ package.access=sun.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
......@@ -225,6 +226,7 @@ package.definition=sun.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
......
......@@ -182,6 +182,7 @@ package.access=sun.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
......@@ -226,6 +227,7 @@ package.definition=sun.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
......
......@@ -183,6 +183,7 @@ package.access=sun.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
......@@ -226,6 +227,7 @@ package.definition=sun.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
......
......@@ -182,6 +182,7 @@ package.access=sun.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
......@@ -226,6 +227,7 @@ package.definition=sun.,\
com.sun.imageio.,\
com.sun.istack.internal.,\
com.sun.jmx.,\
com.sun.media.sound.,\
com.sun.proxy.,\
com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
......
......@@ -90,6 +90,12 @@
#include "classfile_constants.h"
#include "opcodes.in_out"
#ifdef __APPLE__
/* use setjmp/longjmp versions that do not save/restore the signal mask */
#define setjmp _setjmp
#define longjmp _longjmp
#endif
#define MAX_ARRAY_DIMENSIONS 255
/* align byte code */
#ifndef ALIGN_UP
......
......@@ -36,7 +36,7 @@ import java.net.*;
class DatagramDispatcher extends NativeDispatcher
{
static {
Util.load();
IOUtil.load();
}
int read(FileDescriptor fd, long address, int len) throws IOException {
......
......@@ -316,4 +316,8 @@ class DevPollArrayWrapper {
private native int poll0(long pollAddress, int numfds, long timeout,
int wfd);
private static native void interrupt(int fd);
static {
IOUtil.load();
}
}
......@@ -196,9 +196,4 @@ class DevPollSelectorImpl
}
return this;
}
static {
Util.load();
}
}
......@@ -113,6 +113,6 @@ class EPoll {
throws IOException;
static {
Util.load();
IOUtil.load();
}
}
......@@ -318,6 +318,7 @@ class EPollArrayWrapper {
}
static {
IOUtil.load();
init();
}
......
......@@ -318,6 +318,6 @@ final class EPollPort
private static native void close0(int fd);
static {
Util.load();
IOUtil.load();
}
}
......@@ -196,8 +196,4 @@ class EPollSelectorImpl
}
return this;
}
static {
Util.load();
}
}
......@@ -31,7 +31,7 @@ class FileDispatcherImpl extends FileDispatcher
{
static {
Util.load();
IOUtil.load();
init();
}
......
......@@ -235,6 +235,6 @@ class InheritedChannel {
private static native int peerPort0(int fd);
static {
Util.load();
IOUtil.load();
}
}
......@@ -115,6 +115,6 @@ class KQueue {
throws IOException;
static {
Util.load();
IOUtil.load();
}
}
......@@ -326,6 +326,6 @@ final class KQueuePort
private static native void close0(int fd);
static {
Util.load();
IOUtil.load();
}
}
......@@ -54,7 +54,7 @@ public class NativeThread {
private static native void init();
static {
Util.load();
IOUtil.load();
init();
}
......
......@@ -126,4 +126,7 @@ public class PollArrayWrapper extends AbstractPollArrayWrapper {
private static native void interrupt(int fd);
static {
IOUtil.load();
}
}
......@@ -37,7 +37,7 @@ class SinkChannelImpl
{
// Used to make native read and write calls
private static NativeDispatcher nd;
private static final NativeDispatcher nd = new FileDispatcherImpl();
// The file descriptor associated with this channel
FileDescriptor fd;
......@@ -206,10 +206,4 @@ class SinkChannelImpl
throw new IndexOutOfBoundsException();
return write(Util.subsequence(srcs, offset, length));
}
static {
Util.load();
nd = new FileDispatcherImpl();
}
}
......@@ -260,6 +260,6 @@ class SolarisEventPort
static {
Util.load();
IOUtil.load();
}
}
......@@ -37,7 +37,7 @@ class SourceChannelImpl
{
// Used to make native read and write calls
private static NativeDispatcher nd;
private static final NativeDispatcher nd = new FileDispatcherImpl();
// The file descriptor associated with this channel
FileDescriptor fd;
......@@ -206,10 +206,4 @@ class SourceChannelImpl
}
}
}
static {
Util.load();
nd = new FileDispatcherImpl();
}
}
......@@ -345,7 +345,7 @@ class UnixAsynchronousServerSocketChannelImpl
throws IOException;
static {
Util.load();
IOUtil.load();
initIDs();
}
}
......@@ -748,6 +748,6 @@ class UnixAsynchronousSocketChannelImpl
private static native void checkConnect(int fdVal) throws IOException;
static {
Util.load();
IOUtil.load();
}
}
......@@ -1106,7 +1106,7 @@ public class SctpChannelImpl extends SctpChannel
boolean ready) throws IOException;
static {
Util.load(); /* loads nio & net native libraries */
IOUtil.load(); /* loads nio & net native libraries */
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
......
......@@ -995,7 +995,7 @@ public class SctpMultiChannelImpl extends SctpMultiChannel
}
static {
Util.load(); /* loads nio & net native libraries */
IOUtil.load(); /* loads nio & net native libraries */
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
......
......@@ -426,7 +426,7 @@ public class SctpServerChannelImpl extends SctpServerChannel
FileDescriptor newfd, InetSocketAddress[] isaa) throws IOException;
static {
Util.load(); // loads nio & net native libraries
IOUtil.load(); // loads nio & net native libraries
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
......
......@@ -36,7 +36,7 @@ import java.net.*;
class DatagramDispatcher extends NativeDispatcher
{
static {
Util.load();
IOUtil.load();
}
int read(FileDescriptor fd, long address, int len) throws IOException {
......
......@@ -32,7 +32,7 @@ import sun.misc.JavaIOFileDescriptorAccess;
class FileDispatcherImpl extends FileDispatcher
{
static {
Util.load();
IOUtil.load();
}
/**
......
......@@ -73,6 +73,7 @@ public class FileKey {
private static native void initIDs();
static {
IOUtil.load();
initIDs();
}
}
......@@ -443,7 +443,7 @@ class Iocp extends AsynchronousChannelGroupImpl {
private static native String getErrorMessage(int error);
static {
Util.load();
IOUtil.load();
initIDs();
// thread agnostic I/O on Vista/2008 or newer
......
......@@ -56,7 +56,6 @@ class PipeImpl
private static final Random rnd;
static {
Util.load();
byte[] someBytes = new byte[8];
boolean resultOK = IOUtil.randomBytes(someBytes);
if (resultOK) {
......
......@@ -36,7 +36,7 @@ class SocketDispatcher extends NativeDispatcher
{
static {
Util.load();
IOUtil.load();
}
int read(FileDescriptor fd, long address, int len) throws IOException {
......
......@@ -750,6 +750,6 @@ public class WindowsAsynchronousFileChannelImpl
private static native void close0(long handle);
static {
Util.load();
IOUtil.load();
}
}
......@@ -363,7 +363,7 @@ class WindowsAsynchronousServerSocketChannelImpl
private static native void closesocket0(long socket) throws IOException;
static {
Util.load();
IOUtil.load();
initIDs();
}
}
......@@ -919,7 +919,7 @@ class WindowsAsynchronousSocketChannelImpl
private static native void closesocket0(long socket) throws IOException;
static {
Util.load();
IOUtil.load();
initIDs();
}
}
......@@ -611,6 +611,6 @@ final class WindowsSelectorImpl extends SelectorImpl {
}
static {
Util.load();
IOUtil.load();
}
}
......@@ -208,7 +208,7 @@ sun/net/www/http/HttpClient/ProxyTest.java generic-all
# jdk_io
# 7160013
java/io/File/MaxPathLength.java windows-all
#java/io/File/MaxPathLength.java windows-all
############################################################################
......@@ -336,12 +336,6 @@ com/sun/jdi/SuspendThreadTest.java generic-all
# Filed 6653793
com/sun/jdi/RedefineCrossEvent.java generic-all
# Filed 6987312
com/sun/jdi/DoubleAgentTest.java generic-all
# Filed 7020857
com/sun/jdi/FieldWatchpoints.java generic-all
# Filed 6402201
com/sun/jdi/ProcessAttachTest.sh generic-all
......
......@@ -9,3 +9,6 @@ othervm.dirs=java/awt java/beans java/rmi javax/accessibility javax/imageio java
# Tests that cannot run concurrently
exclusiveAccess.dirs=java/rmi/Naming java/util/Currency java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi
# Group definitions
groups=TEST.groups [closed/TEST.groups]
# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
jdk_lang = \
java/lang \
-java/lang/management \
-java/lang/instrument \
sun/invoke \
sun/misc \
sun/reflect \
vm
jdk_util = \
java/util \
sun/util
jdk_math = \
java/math
jdk_io = \
java/io
jdk_nio = \
java/nio \
sun/nio
jdk_net = \
java/net \
com/sun/net \
com/oracle/net \
sun/net
jdk_time = \
java/time
jdk_rmi = \
java/rmi \
javax/rmi/ssl \
sun/rmi
jdk_security1 = \
java/security
jdk_security2 = \
javax/crypto \
javax/xml/crypto \
com/sun/crypto
jdk_security3 = \
javax/security \
com/sun/security \
com/sun/org/apache/xml/internal/security \
com/oracle/security \
sun/security \
lib/security
jdk_security = \
:jdk_security1 \
:jdk_security2 \
:jdk_security3
jdk_text = \
java/text \
sun/text
jdk_management = \
java/lang/management \
com/sun/management \
sun/management
jdk_instrument = \
java/lang/instrument
jdk_jmx = \
javax/management \
com/sun/jmx
jdk_jdi = \
com/sun/jdi
#
# Tool (and tool API) tests are split into core and svc groups
#
core_tools = \
tools \
com/sun/tools/extcheck \
sun/tools/java \
sun/tools/native2ascii \
sun/tools/jrunscript
svc_tools = \
com/sun/tools/attach \
com/sun/tracing \
sun/tools \
-sun/tools/java \
-sun/tools/native2ascii \
-sun/tools/jrunscript \
sun/jvmstat \
demo/jvmti
jdk_tools = \
:core_tools \
:svc_tools
#
# Catch-all for other areas with a small number of tests
#
jdk_other = \
java/sql \
javax/sql \
javax/naming \
javax/script \
javax/smartcardio \
javax/xml \
-javax/xml/crypto \
jdk/asm \
jdk/lambda \
com/sun/jndi \
com/sun/corba \
lib/testlibrary \
demo/zipfs \
sample
#
# SCTP is its own group as it is highly sensitive to kernel/network config
#
jdk_sctp = \
com/sun/nio/sctp
#
# core group to run all core area tests
#
jdk_core = \
:jdk_lang \
:jdk_util \
:jdk_math \
:jdk_io \
:jdk_nio \
:jdk_net \
:jdk_rmi \
:jdk_time \
:jdk_security \
:jdk_text \
:core_tools \
:jdk_other
#
# svc group to run all serviceability area tests
#
jdk_svc = \
:jdk_management \
:jdk_instrument \
:jdk_jmx \
:jdk_jdi \
:svc_tools
#############################
#
# Client area groups
#
jdk_awt = \
java/awt \
com/sun/awt \
com/apple/eawt \
sun/awt
jdk_2d = \
javax/print \
sun/pisces \
sun/java2d
jdk_beans = \
java/beans
jdk_swing = \
javax/accessibility \
javax/swing \
com/sun/java/swing
jdk_sound = \
javax/sound
jdk_imageio = \
javax/imageio
jdk_desktop = \
:jdk_awt \
:jdk_2d \
:jdk_beans \
:jdk_swing \
:jdk_sound \
:jdk_imageio
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
* @bug 7129312
* @summary BufferedInputStream calculates negative array size with large
* streams and mark
* @library /lib/testlibrary
* @run main/othervm LargeCopyWithMark
*/
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import static jdk.testlibrary.ProcessTools.*;
public class LargeCopyWithMark {
public static void main(String[] args) throws Exception {
if (! System.getProperty("os.arch").contains("64")) {
System.out.println("Test runs on 64 bit platforms");
return;
}
ProcessBuilder pb = createJavaProcessBuilder("-Xmx4G",
"-ea:LargeCopyWithMark$Child",
"LargeCopyWithMark$Child");
int res = pb.inheritIO().start().waitFor();
if (res != 0) {
throw new AssertionError("Test failed: exit code = " + res);
}
}
public static class Child {
static final int BUFF_SIZE = 8192;
static final int BIS_BUFF_SIZE = Integer.MAX_VALUE / 2 + 100;
static final long BYTES_TO_COPY = 2L * Integer.MAX_VALUE;
static {
assert BIS_BUFF_SIZE * 2 < 0 : "doubling must overflow";
}
public static void main(String[] args) throws Exception {
byte[] buff = new byte[BUFF_SIZE];
try (InputStream myis = new MyInputStream(BYTES_TO_COPY);
InputStream bis = new BufferedInputStream(myis, BIS_BUFF_SIZE);
OutputStream myos = new MyOutputStream()) {
// will require a buffer bigger than BIS_BUFF_SIZE
bis.mark(BIS_BUFF_SIZE + 100);
for (;;) {
int count = bis.read(buff, 0, BUFF_SIZE);
if (count == -1)
break;
myos.write(buff, 0, count);
}
} catch (java.lang.NegativeArraySizeException e) {
e.printStackTrace();
System.exit(11);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class MyInputStream extends InputStream {
private long bytesLeft;
public MyInputStream(long bytesLeft) {
this.bytesLeft = bytesLeft;
}
@Override public int read() throws IOException {
return 0;
}
@Override public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override public int read(byte[] b, int off, int len) throws IOException {
if (bytesLeft <= 0)
return -1;
long result = Math.min(bytesLeft, (long)len);
bytesLeft -= result;
return (int)result;
}
@Override public int available() throws IOException {
return (bytesLeft > 0) ? 1 : 0;
}
}
class MyOutputStream extends OutputStream {
@Override public void write(int b) throws IOException {}
@Override public void write(byte[] b) throws IOException {}
@Override public void write(byte[] b, int off, int len) throws IOException {}
}
/*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -27,6 +27,7 @@
*/
import java.io.*;
import java.nio.file.Files;
public class MaxPathLength {
private static String sep = File.separator;
......@@ -87,10 +88,8 @@ public class MaxPathLength {
System.err.println("Warning: Test directory structure exists already!");
return;
}
boolean couldMakeTestDirectory = dirFile.mkdirs();
if (!couldMakeTestDirectory) {
throw new RuntimeException ("Could not create test directory structure");
}
Files.createDirectories(dirFile.toPath());
try {
if (tryAbsolute)
dirFile = new File(dirFile.getCanonicalPath());
......
......@@ -28,6 +28,7 @@
import java.io.*;
import java.util.*;
import java.nio.file.*;
public class General {
......@@ -57,7 +58,7 @@ public class General {
for (int i = 0; i < dl.length; i++) {
File f = new File(subdir, dl[i]);
File df = new File(dir, f.getPath());
if (df.exists() && df.isFile()) {
if (Files.isRegularFile(df.toPath(), LinkOption.NOFOLLOW_LINKS)) {
return f.getPath();
}
}
......@@ -65,7 +66,7 @@ public class General {
File f = (subdir.length() == 0) ? new File(dl[i])
: new File(subdir, dl[i]);
File df = new File(dir, f.getPath());
if (df.exists() && df.isDirectory()) {
if (Files.isDirectory(df.toPath(), LinkOption.NOFOLLOW_LINKS)) {
String[] dl2 = df.list();
if (dl2 != null) {
String ff = findSomeFile(dir, f.getPath(), dl2);
......@@ -90,7 +91,7 @@ public class General {
}
for (int i = 0; i < dl.length; i++) {
File f = new File(dir, dl[i]);
if (f.isFile()) {
if (Files.isRegularFile(f.toPath(), LinkOption.NOFOLLOW_LINKS)) {
return dl[i];
}
}
......@@ -127,7 +128,7 @@ public class General {
}
for (int i = 0; i < dl.length; i++) {
File f = new File(d, dl[i]);
if (f.isDirectory()) {
if (Files.isDirectory(f.toPath(), LinkOption.NOFOLLOW_LINKS)) {
String[] dl2 = f.list();
if (dl2 == null || dl2.length >= 250) {
/* Heuristic to avoid scanning huge directories */
......@@ -314,7 +315,7 @@ public class General {
/* Normal name */
if (f.exists()) {
if (f.isDirectory() && f.list() != null) {
if (Files.isDirectory(f.toPath(), LinkOption.NOFOLLOW_LINKS) && f.list() != null) {
if ((n = findSomeFile(ans, create)) != null)
checkSlashes(d, create, ans + n, ask + n);
if ((n = findSomeDir(ans, create)) != null)
......
......@@ -23,7 +23,7 @@
/*
* @test
* @bug 6741606 7146431 8000450
* @bug 6741606 7146431 8000450 8019830
* @summary Make sure all restricted packages listed in the package.access
* property in the java.security file are blocked
* @run main/othervm CheckPackageAccess
......@@ -54,6 +54,7 @@ public class CheckPackageAccess {
"com.sun.imageio.",
"com.sun.istack.internal.",
"com.sun.jmx.",
"com.sun.media.sound.",
"com.sun.proxy.",
"com.sun.org.apache.bcel.internal.",
"com.sun.org.apache.regexp.internal.",
......
......@@ -28,6 +28,9 @@
*/
import java.lang.annotation.Retention;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
......@@ -66,17 +69,6 @@ public class AnnotationTypeDeadlockTest {
}
}
static void dumpState(Task task) {
System.err.println(
"Task[" + task.getName() + "].state: " +
task.getState() + " ..."
);
for (StackTraceElement ste : task.getStackTrace()) {
System.err.println("\tat " + ste);
}
System.err.println();
}
public static void main(String[] args) throws Exception {
CountDownLatch prepareLatch = new CountDownLatch(2);
AtomicInteger goLatch = new AtomicInteger(1);
......@@ -88,18 +80,22 @@ public class AnnotationTypeDeadlockTest {
prepareLatch.await();
// let them go
goLatch.set(0);
// attempt to join them
taskA.join(5000L);
taskB.join(5000L);
if (taskA.isAlive() || taskB.isAlive()) {
dumpState(taskA);
dumpState(taskB);
throw new IllegalStateException(
taskA.getState() == Thread.State.BLOCKED &&
taskB.getState() == Thread.State.BLOCKED
? "deadlock detected"
: "unexpected condition");
// obtain ThreadMXBean
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
// wait for threads to finish or dead-lock
while (taskA.isAlive() || taskB.isAlive()) {
// attempt to join threads
taskA.join(500L);
taskB.join(500L);
// detect dead-lock
long[] deadlockedIds = threadBean.findMonitorDeadlockedThreads();
if (deadlockedIds != null && deadlockedIds.length > 0) {
StringBuilder sb = new StringBuilder("deadlock detected:\n\n");
for (ThreadInfo ti : threadBean.getThreadInfo(deadlockedIds, Integer.MAX_VALUE)) {
sb.append(ti);
}
throw new IllegalStateException(sb.toString());
}
}
}
}
......@@ -23,7 +23,7 @@
/*
* @test
* @bug 8004698 8007073
* @bug 8004698 8007073 8022343
* @summary Unit test for type annotations
*/
......@@ -58,7 +58,7 @@ public class TypeAnnotationReflection {
}
private static void testSuper() throws Exception {
check(Object.class.getAnnotatedSuperclass().getAnnotations().length == 0);
check(Object.class.getAnnotatedSuperclass() == null);
check(Class.class.getAnnotatedSuperclass().getAnnotations().length == 0);
AnnotatedType a;
......
/*
* Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
......@@ -23,52 +21,36 @@
* questions.
*/
/**
* Sort: a class that uses the quicksort algorithm to sort an
* array of objects.
*
* @author Sunita Mani
*/
package sun.misc;
public class Sort {
private static void swap(Object arr[], int i, int j) {
Object tmp;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
/**
* quicksort the array of objects.
*
* @param arr[] - an array of objects
* @param left - the start index - from where to begin sorting
* @param right - the last index.
* @param comp - an object that implemnts the Compare interface to resolve thecomparison.
/*
* @test
* @bug 8022343
* @summary make sure Class.getAnnotatedSuperclass() returns null when specified to do so
*/
public static void quicksort(Object arr[], int left, int right, Compare comp) {
int i, last;
if (left >= right) { /* do nothing if array contains fewer than two */
return; /* two elements */
public class GetAnnotatedSuperclass {
private static final Class<?>[] testData = {
Object.class,
If.class,
Object[].class,
void.class,
int.class,
};
public static void main(String[] args) throws Exception {
int failed = 0;
for (Class<?> toTest : testData) {
Object res = toTest.getAnnotatedSuperclass();
if (res != null) {
failed++;
System.out.println(toTest + ".getAnnotatedSuperclass() returns: "
+ res + ", should be null");
}
swap(arr, left, (left+right) / 2);
last = left;
for (i = left+1; i <= right; i++) {
if (comp.doCompare(arr[i], arr[left]) < 0) {
swap(arr, ++last, i);
}
}
swap(arr, left, last);
quicksort(arr, left, last-1, comp);
quicksort(arr, last+1, right, comp);
}
public static void quicksort(Object arr[], Compare comp) {
quicksort(arr, 0, arr.length-1, comp);
if (failed != 0)
throw new RuntimeException("Test failed, check log for details");
}
interface If {}
}
......@@ -33,10 +33,10 @@
* @author Mandy Chung
*
* @build ResetPeakMemoryUsage MemoryUtil
* @run main/othervm -XX:+UseSerialGC -XX:MarkSweepAlwaysCompactCount=1 -Xmn8m ResetPeakMemoryUsage
* @run main/othervm -XX:+UseConcMarkSweepGC -Xmn8m ResetPeakMemoryUsage
* @run main/othervm -XX:+UseParallelGC -Xmn8m ResetPeakMemoryUsage
* @run main/othervm -XX:+UseG1GC -Xmn8m -XX:G1HeapRegionSize=1m ResetPeakMemoryUsage
* @run main/othervm -XX:+PrintGCDetails -XX:+UseSerialGC -Xms256m -XX:MarkSweepAlwaysCompactCount=1 -Xmn8m ResetPeakMemoryUsage
* @run main/othervm -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC -Xms256m -Xmn8m ResetPeakMemoryUsage
* @run main/othervm -XX:+PrintGCDetails -XX:+UseParallelGC -Xms256m -Xmn8m ResetPeakMemoryUsage
* @run main/othervm -XX:+PrintGCDetails -XX:+UseG1GC -Xms256m -Xmn8m -XX:G1HeapRegionSize=1m ResetPeakMemoryUsage
*/
import java.lang.management.*;
......
......@@ -22,7 +22,7 @@
*/
/*
* @test
* @bug 4904082 4917089 6337226
* @bug 4904082 4917089 6337226 6378503
* @summary Tests that integral division and related methods return the proper result and scale.
* @author Joseph D. Darcy
*/
......@@ -47,6 +47,9 @@ public class IntegralDivisionTests {
{new BigDecimal("400e1"), new BigDecimal("5"), new BigDecimal("80e1")},
{new BigDecimal("400e1"), new BigDecimal("4.999999999"), new BigDecimal("8e2")},
{new BigDecimal("40e2"), new BigDecimal("5"), new BigDecimal("8e2")},
{BigDecimal.valueOf(1, Integer.MIN_VALUE),
BigDecimal.valueOf(1, -(Integer.MAX_VALUE & 0x7fffff00)),
BigDecimal.valueOf(1, -256)},
};
for(BigDecimal [] testCase: moreTestCases) {
......
......@@ -54,7 +54,7 @@ public class SensitivityModifier {
@SuppressWarnings("unchecked")
static void doTest(Path top) throws Exception {
FileSystem fs = top.getFileSystem();
WatchService watcher = fs.newWatchService();
try (WatchService watcher = fs.newWatchService()) {
// create directories and files
int nDirs = 5 + rand.nextInt(20);
......@@ -84,30 +84,36 @@ public class SensitivityModifier {
try (OutputStream out = Files.newOutputStream(file)) {
out.write(new byte[100]);
}
System.out.println("Waiting for event...");
System.out.println("Waiting for event(s)...");
boolean eventReceived = false;
WatchKey key = watcher.take();
WatchEvent<?> event = key.pollEvents().iterator().next();
do {
for (WatchEvent<?> event: key.pollEvents()) {
if (event.kind() != ENTRY_MODIFY)
throw new RuntimeException("Unexpected event: " + event);
Path name = ((WatchEvent<Path>)event).context();
if (!name.equals(file.getFileName()))
throw new RuntimeException("Unexpected context: " + name);
System.out.println("Event OK");
// drain events (to avoid interference)
do {
key.pollEvents();
if (name.equals(file.getFileName())) {
eventReceived = true;
break;
}
}
key.reset();
key = watcher.poll(1, TimeUnit.SECONDS);
} while (key != null);
} while (key != null && !eventReceived);
// we should have received at least one ENTRY_MODIFY event
if (eventReceived) {
System.out.println("Event OK");
} else {
throw new RuntimeException("No ENTRY_MODIFY event received for " + file);
}
// re-register the directories to force changing their sensitivity
// level
register(dirs, watcher);
}
// done
watcher.close();
}
}
public static void main(String[] args) throws Exception {
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8011944
* @summary Test TimSort stack size
*/
import java.util.Arrays;
import java.util.ArrayDeque;
public class TimSortStackSize {
public static void main(String[] args) {
testComparableTimSort();
testTimSort();
}
static void testComparableTimSort() {
System.out.printf("testComparableTimSort()%n");
Arrays.sort(genData());
}
static void testTimSort() {
System.out.printf("testTimSort()%n");
Arrays.sort(genData(), Integer::compare);
}
private static final int MIN = 16;
private static final int BOUND1 = 2 * MIN + 1;
private static final int BOUND2 = BOUND1 + MIN + 2;
private static final int BOUND3 = BOUND1 + 1 + BOUND2;
private static final int BOUND4 = BOUND2 + 1 + BOUND3;
private static final int BOUND5 = BOUND3 + 1 + BOUND4;
static int build(int size, int B, ArrayDeque<Integer> chunks) {
chunks.addFirst(B);
if (size < BOUND1) {
chunks.addFirst(size);
return size;
}
int asize = (size + 2) / 2;
if (size >= BOUND2 && asize < BOUND1) {
asize = BOUND1;
} else if (size >= BOUND3 && asize < BOUND2) {
asize = BOUND2;
} else if (size >= BOUND4 && asize < BOUND3) {
asize = BOUND3;
} else if (size >= BOUND5 && asize < BOUND4) {
asize = BOUND4;
}
if (size - asize >= B) {
throw new AssertionError(" " + size + " , " + asize + " , " + B);
}
return build(asize, size - asize, chunks);
}
static Integer[] genData() {
ArrayDeque<Integer> chunks = new ArrayDeque<Integer>();
chunks.addFirst(MIN);
int B = MIN + 4;
int A = B + MIN + 1;
for (int i = 0; i < 8; i++) {
int eps = build(A, B, chunks);
B = B + A + 1;
A = B + eps + 1;
}
chunks.addFirst(B);
chunks.addFirst(A);
int total = 0;
for (Integer len : chunks) {
total += len;
}
int pow = MIN;
while (pow < total) {
pow += pow;
}
chunks.addLast(pow - total);
System.out.println(" Total: " + total);
Integer[] array = new Integer[pow];
int off = 0;
int pos = 0;
for (Integer len : chunks) {
for (int i = 0; i < len; i++) {
array[pos++] = Integer.valueOf(i == 0 ? 0 : 1);
}
off++;
}
return array;
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @run testng Wrappers
* @summary Ensure Collections wrapping classes provide non-default implementations
*/
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.TreeMap;
import java.util.TreeSet;
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
import static org.testng.Assert.assertFalse;
@Test(groups = "unit")
public class Wrappers {
static Object[][] collections;
@DataProvider(name="collections")
public static Object[][] collectionCases() {
if (collections != null) {
return collections;
}
List<Object[]> cases = new ArrayList<>();
LinkedList<Integer> seedList = new LinkedList<>();
ArrayList<Integer> seedRandomAccess = new ArrayList<>();
TreeSet<Integer> seedSet = new TreeSet<>();
TreeMap<Integer, Integer> seedMap = new TreeMap<>();
for (int i = 1; i <= 10; i++) {
seedList.add(i);
seedRandomAccess.add(i);
seedSet.add(i);
seedMap.put(i, i);
}
cases.add(new Object[] { Collections.unmodifiableCollection(seedList) });
cases.add(new Object[] { Collections.unmodifiableList(seedList) });
cases.add(new Object[] { Collections.unmodifiableList(seedRandomAccess) });
cases.add(new Object[] { Collections.unmodifiableSet(seedSet) });
cases.add(new Object[] { Collections.unmodifiableSortedSet(seedSet) });
cases.add(new Object[] { Collections.unmodifiableNavigableSet(seedSet) });
// As sets from map also need to be unmodifiable, thus a wrapping
// layer exist and should not have default methods
cases.add(new Object[] { Collections.unmodifiableMap(seedMap).entrySet() });
cases.add(new Object[] { Collections.unmodifiableMap(seedMap).keySet() });
cases.add(new Object[] { Collections.unmodifiableMap(seedMap).values() });
cases.add(new Object[] { Collections.unmodifiableSortedMap(seedMap).entrySet() });
cases.add(new Object[] { Collections.unmodifiableSortedMap(seedMap).keySet() });
cases.add(new Object[] { Collections.unmodifiableSortedMap(seedMap).values() });
cases.add(new Object[] { Collections.unmodifiableNavigableMap(seedMap).entrySet() });
cases.add(new Object[] { Collections.unmodifiableNavigableMap(seedMap).keySet() });
cases.add(new Object[] { Collections.unmodifiableNavigableMap(seedMap).values() });
// Synchronized
cases.add(new Object[] { Collections.synchronizedCollection(seedList) });
cases.add(new Object[] { Collections.synchronizedList(seedList) });
cases.add(new Object[] { Collections.synchronizedList(seedRandomAccess) });
cases.add(new Object[] { Collections.synchronizedSet(seedSet) });
cases.add(new Object[] { Collections.synchronizedSortedSet(seedSet) });
cases.add(new Object[] { Collections.synchronizedNavigableSet(seedSet) });
// As sets from map also need to be synchronized on the map, thus a
// wrapping layer exist and should not have default methods
cases.add(new Object[] { Collections.synchronizedMap(seedMap).entrySet() });
cases.add(new Object[] { Collections.synchronizedMap(seedMap).keySet() });
cases.add(new Object[] { Collections.synchronizedMap(seedMap).values() });
cases.add(new Object[] { Collections.synchronizedSortedMap(seedMap).entrySet() });
cases.add(new Object[] { Collections.synchronizedSortedMap(seedMap).keySet() });
cases.add(new Object[] { Collections.synchronizedSortedMap(seedMap).values() });
cases.add(new Object[] { Collections.synchronizedNavigableMap(seedMap).entrySet() });
cases.add(new Object[] { Collections.synchronizedNavigableMap(seedMap).keySet() });
cases.add(new Object[] { Collections.synchronizedNavigableMap(seedMap).values() });
// Checked
cases.add(new Object[] { Collections.checkedCollection(seedList, Integer.class) });
cases.add(new Object[] { Collections.checkedList(seedList, Integer.class) });
cases.add(new Object[] { Collections.checkedList(seedRandomAccess, Integer.class) });
cases.add(new Object[] { Collections.checkedSet(seedSet, Integer.class) });
cases.add(new Object[] { Collections.checkedSortedSet(seedSet, Integer.class) });
cases.add(new Object[] { Collections.checkedNavigableSet(seedSet, Integer.class) });
cases.add(new Object[] { Collections.checkedQueue(seedList, Integer.class) });
// asLifoQueue is another wrapper
cases.add(new Object[] { Collections.asLifoQueue(seedList) });
collections = cases.toArray(new Object[0][]);
return collections;
}
static Method[] defaultMethods;
static {
List<Method> list = new ArrayList<>();
Method[] methods = Collection.class.getMethods();
for (Method m: methods) {
if (m.isDefault()) {
list.add(m);
}
}
defaultMethods = list.toArray(new Method[0]);
}
@Test(dataProvider = "collections")
public static void testAllDefaultMethodsOverridden(Collection c) throws NoSuchMethodException {
Class cls = c.getClass();
for (Method m: defaultMethods) {
Method m2 = cls.getMethod(m.getName(), m.getParameterTypes());
// default had been override
assertFalse(m2.isDefault(), cls.getCanonicalName());
}
}
}
......@@ -90,7 +90,7 @@ public class BasicTest {
Thing[] things = new Thing[intValues.length];
for (int i=0; i<intValues.length; i++)
things[i] = new Thing(intValues[i], 0L, 0.0, null);
Comparator<Thing> comp = Comparator.comparing(new ToIntFunction<Thing>() {
Comparator<Thing> comp = Comparator.comparingInt(new ToIntFunction<Thing>() {
@Override
public int applyAsInt(Thing thing) {
return thing.getIntField();
......@@ -104,7 +104,7 @@ public class BasicTest {
Thing[] things = new Thing[longValues.length];
for (int i=0; i<longValues.length; i++)
things[i] = new Thing(0, longValues[i], 0.0, null);
Comparator<Thing> comp = Comparator.comparing(new ToLongFunction<Thing>() {
Comparator<Thing> comp = Comparator.comparingLong(new ToLongFunction<Thing>() {
@Override
public long applyAsLong(Thing thing) {
return thing.getLongField();
......@@ -118,7 +118,7 @@ public class BasicTest {
Thing[] things = new Thing[doubleValues.length];
for (int i=0; i<doubleValues.length; i++)
things[i] = new Thing(0, 0L, doubleValues[i], null);
Comparator<Thing> comp = Comparator.comparing(new ToDoubleFunction<Thing>() {
Comparator<Thing> comp = Comparator.comparingDouble(new ToDoubleFunction<Thing>() {
@Override
public double applyAsDouble(Thing thing) {
return thing.getDoubleField();
......@@ -211,8 +211,8 @@ public class BasicTest {
};
public void testComparatorDefaultMethods() {
Comparator<People> cmp = Comparator.comparing((Function<People, String>) People::getFirstName);
Comparator<People> cmp2 = Comparator.comparing((Function<People, String>) People::getLastName);
Comparator<People> cmp = Comparator.comparing(People::getFirstName);
Comparator<People> cmp2 = Comparator.comparing(People::getLastName);
// reverseOrder
assertComparison(cmp.reversed(), people[1], people[0]);
// thenComparing(Comparator)
......@@ -222,20 +222,20 @@ public class BasicTest {
assertComparison(cmp.thenComparing(People::getLastName), people[0], people[1]);
assertComparison(cmp.thenComparing(People::getLastName), people[4], people[0]);
// thenComparing(ToIntFunction)
assertComparison(cmp.thenComparing(People::getAge), people[0], people[1]);
assertComparison(cmp.thenComparing(People::getAge), people[1], people[5]);
assertComparison(cmp.thenComparingInt(People::getAge), people[0], people[1]);
assertComparison(cmp.thenComparingInt(People::getAge), people[1], people[5]);
// thenComparing(ToLongFunction)
assertComparison(cmp.thenComparing(People::getAgeAsLong), people[0], people[1]);
assertComparison(cmp.thenComparing(People::getAgeAsLong), people[1], people[5]);
assertComparison(cmp.thenComparingLong(People::getAgeAsLong), people[0], people[1]);
assertComparison(cmp.thenComparingLong(People::getAgeAsLong), people[1], people[5]);
// thenComparing(ToDoubleFunction)
assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[0], people[1]);
assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[1], people[5]);
assertComparison(cmp.thenComparingDouble(People::getAgeAsDouble), people[0], people[1]);
assertComparison(cmp.thenComparingDouble(People::getAgeAsDouble), people[1], people[5]);
}
public void testNullsFirst() {
Comparator<String> strcmp = Comparator.nullsFirst(Comparator.naturalOrder());
Comparator<People> cmp = Comparator.<People, String>comparing(People::getLastName, strcmp)
Comparator<People> cmp = Comparator.comparing(People::getLastName, strcmp)
.thenComparing(People::getFirstName, strcmp);
// Mary.null vs Mary.Cook - solve by last name
assertComparison(cmp, people[6], people[5]);
......@@ -243,7 +243,7 @@ public class BasicTest {
assertComparison(cmp, people[7], people[6]);
// More than one thenComparing
strcmp = Comparator.nullsFirst(Comparator.comparing((ToIntFunction<String>) String::length)
strcmp = Comparator.nullsFirst(Comparator.comparingInt(String::length)
.thenComparing(String.CASE_INSENSITIVE_ORDER));
assertComparison(strcmp, null, "abc");
assertComparison(strcmp, "ab", "abc");
......@@ -273,7 +273,7 @@ public class BasicTest {
public void testNullsLast() {
Comparator<String> strcmp = Comparator.nullsLast(Comparator.naturalOrder());
Comparator<People> cmp = Comparator.<People, String>comparing(People::getLastName, strcmp)
Comparator<People> cmp = Comparator.comparing(People::getLastName, strcmp)
.thenComparing(People::getFirstName, strcmp);
// Mary.null vs Mary.Cook - solve by last name
assertComparison(cmp, people[5], people[6]);
......@@ -281,7 +281,7 @@ public class BasicTest {
assertComparison(cmp, people[7], people[6]);
// More than one thenComparing
strcmp = Comparator.nullsLast(Comparator.comparing((ToIntFunction<String>) String::length)
strcmp = Comparator.nullsLast(Comparator.comparingInt(String::length)
.thenComparing(String.CASE_INSENSITIVE_ORDER));
assertComparison(strcmp, "abc", null);
assertComparison(strcmp, "ab", "abc");
......@@ -341,28 +341,28 @@ public class BasicTest {
} catch (NullPointerException npe) {}
try {
Comparator<People> cmp = Comparator.comparing((Function<People, String>) null, Comparator.<String>naturalOrder());
Comparator<People> cmp = Comparator.comparing(null, Comparator.<String>naturalOrder());
fail("comparing(null, cmp) should throw NPE");
} catch (NullPointerException npe) {}
try {
Comparator<People> cmp = Comparator.comparing((Function<People, String>) People::getFirstName, null);
Comparator<People> cmp = Comparator.comparing(People::getFirstName, null);
fail("comparing(f, null) should throw NPE");
} catch (NullPointerException npe) {}
try {
Comparator<People> cmp = Comparator.comparing((Function<People, String>) null);
Comparator<People> cmp = Comparator.comparing(null);
fail("comparing(null) should throw NPE");
} catch (NullPointerException npe) {}
try {
Comparator<People> cmp = Comparator.comparing((ToIntFunction<People>) null);
Comparator<People> cmp = Comparator.comparingInt(null);
fail("comparing(null) should throw NPE");
} catch (NullPointerException npe) {}
try {
Comparator<People> cmp = Comparator.comparing((ToLongFunction<People>) null);
Comparator<People> cmp = Comparator.comparingLong(null);
fail("comparing(null) should throw NPE");
} catch (NullPointerException npe) {}
try {
Comparator<People> cmp = Comparator.comparing((ToDoubleFunction<People>) null);
Comparator<People> cmp = Comparator.comparingDouble(null);
fail("comparing(null) should throw NPE");
} catch (NullPointerException npe) {}
}
......
......@@ -115,8 +115,8 @@ public class EntryComparators {
// Comparator<People> cmp = Comparator.naturalOrder(); // Should fail to compiler as People is not comparable
// We can use simple comparator, but those have been tested above.
// Thus choose to do compose for some level of interation.
Comparator<People> cmp1 = Comparator.comparing((Function<People, String>) People::getFirstName);
Comparator<People> cmp2 = Comparator.comparing((Function<People, String>) People::getLastName);
Comparator<People> cmp1 = Comparator.comparing(People::getFirstName);
Comparator<People> cmp2 = Comparator.comparing(People::getLastName);
Comparator<People> cmp = cmp1.thenComparing(cmp2);
assertPairComparison(people[0], people[0], people[1], people[1],
......
......@@ -82,13 +82,6 @@ public class RandomStreamTest {
assertEquals(destination.size(), count);
}
@Test(dataProvider = "suppliers")
public void testRandomGaussianStream(final Random random, final int count) {
final List<Double> destination = new ArrayList<>(count);
random.gaussians().limit(count).forEach(destination::add);
assertEquals(destination.size(), count);
}
@Test
public void testIntStream() {
final long seed = System.currentTimeMillis();
......@@ -131,20 +124,6 @@ public class RandomStreamTest {
assertEquals(a, b);
}
@Test
public void testGaussianStream() {
final long seed = System.currentTimeMillis();
final Random r1 = new Random(seed);
final double[] a = new double[SIZE];
for (int i=0; i < SIZE; i++) {
a[i] = r1.nextGaussian();
}
final Random r2 = new Random(seed); // same seed
final double[] b = r2.gaussians().limit(SIZE).toArray();
assertEquals(a, b);
}
@Test
public void testThreadLocalIntStream() throws InterruptedException, ExecutionException, TimeoutException {
ThreadLocalRandom tlr = ThreadLocalRandom.current();
......@@ -163,12 +142,6 @@ public class RandomStreamTest {
testRandomResultSupplierConcurrently(() -> tlr.doubles().limit(SIZE).boxed().collect(toList()));
}
@Test
public void testThreadLocalGaussianStream() throws InterruptedException, ExecutionException, TimeoutException {
ThreadLocalRandom tlr = ThreadLocalRandom.current();
testRandomResultSupplierConcurrently(() -> tlr.gaussians().limit(SIZE).boxed().collect(toList()));
}
<T> void testRandomResultSupplierConcurrently(Supplier<T> s) throws InterruptedException, ExecutionException, TimeoutException {
// Produce 10 completable future tasks
final int tasks = 10;
......
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.BiConsumer;
import static org.testng.Assert.*;
/**
* @test
* @run testng RandomTest
* @summary test methods on Random
*/
@Test
public class RandomTest {
// Note: this test was adapted from the 166 TCK ThreadLocalRandomTest test
// and modified to be a TestNG test
/*
* Testing coverage notes:
*
* We don't test randomness properties, but only that repeated
* calls, up to NCALLS tries, produce at least one different
* result. For bounded versions, we sample various intervals
* across multiples of primes.
*/
// max numbers of calls to detect getting stuck on one value
static final int NCALLS = 10000;
// max sampled int bound
static final int MAX_INT_BOUND = (1 << 28);
// max sampled long bound
static final long MAX_LONG_BOUND = (1L << 42);
// Number of replications for other checks
static final int REPS = 20;
/**
* Repeated calls to nextInt produce at least two distinct results
*/
public void testNextInt() {
Random r = new Random();
int f = r.nextInt();
int i = 0;
while (i < NCALLS && r.nextInt() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextLong produce at least two distinct results
*/
public void testNextLong() {
Random r = new Random();
long f = r.nextLong();
int i = 0;
while (i < NCALLS && r.nextLong() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextBoolean produce at least two distinct results
*/
public void testNextBoolean() {
Random r = new Random();
boolean f = r.nextBoolean();
int i = 0;
while (i < NCALLS && r.nextBoolean() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextFloat produce at least two distinct results
*/
public void testNextFloat() {
Random r = new Random();
float f = r.nextFloat();
int i = 0;
while (i < NCALLS && r.nextFloat() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextDouble produce at least two distinct results
*/
public void testNextDouble() {
Random r = new Random();
double f = r.nextDouble();
int i = 0;
while (i < NCALLS && r.nextDouble() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextGaussian produce at least two distinct results
*/
public void testNextGaussian() {
Random r = new Random();
double f = r.nextGaussian();
int i = 0;
while (i < NCALLS && r.nextGaussian() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* nextInt(negative) throws IllegalArgumentException
*/
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNextIntBoundedNeg() {
Random r = new Random();
int f = r.nextInt(-17);
}
/**
* nextInt(bound) returns 0 <= value < bound; repeated calls produce at
* least two distinct results
*/
public void testNextIntBounded() {
Random r = new Random();
// sample bound space across prime number increments
for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
int f = r.nextInt(bound);
assertTrue(0 <= f && f < bound);
int i = 0;
int j;
while (i < NCALLS &&
(j = r.nextInt(bound)) == f) {
assertTrue(0 <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
/**
* Invoking sized ints, long, doubles, with negative sizes throws
* IllegalArgumentException
*/
public void testBadStreamSize() {
Random r = new Random();
executeAndCatchIAE(() -> r.ints(-1L));
executeAndCatchIAE(() -> r.ints(-1L, 2, 3));
executeAndCatchIAE(() -> r.longs(-1L));
executeAndCatchIAE(() -> r.longs(-1L, -1L, 1L));
executeAndCatchIAE(() -> r.doubles(-1L));
executeAndCatchIAE(() -> r.doubles(-1L, .5, .6));
}
/**
* Invoking bounded ints, long, doubles, with illegal bounds throws
* IllegalArgumentException
*/
public void testBadStreamBounds() {
Random r = new Random();
executeAndCatchIAE(() -> r.ints(2, 1));
executeAndCatchIAE(() -> r.ints(10, 42, 42));
executeAndCatchIAE(() -> r.longs(-1L, -1L));
executeAndCatchIAE(() -> r.longs(10, 1L, -2L));
testDoubleBadOriginBound((o, b) -> r.doubles(10, o, b));
}
// An arbitrary finite double value
static final double FINITE = Math.PI;
void testDoubleBadOriginBound(BiConsumer<Double, Double> bi) {
executeAndCatchIAE(() -> bi.accept(17.0, 2.0));
executeAndCatchIAE(() -> bi.accept(0.0, 0.0));
executeAndCatchIAE(() -> bi.accept(Double.NaN, FINITE));
executeAndCatchIAE(() -> bi.accept(FINITE, Double.NaN));
executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
// Returns NaN
// executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, FINITE));
// executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
executeAndCatchIAE(() -> bi.accept(FINITE, Double.NEGATIVE_INFINITY));
// Returns Double.MAX_VALUE
// executeAndCatchIAE(() -> bi.accept(FINITE, Double.POSITIVE_INFINITY));
executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, FINITE));
executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
}
private void executeAndCatchIAE(Runnable r) {
executeAndCatch(IllegalArgumentException.class, r);
}
private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
Exception caught = null;
try {
r.run();
}
catch (Exception e) {
caught = e;
}
assertNotNull(caught,
String.format("No Exception was thrown, expected an Exception of %s to be thrown",
expected.getName()));
Assert.assertTrue(expected.isInstance(caught),
String.format("Exception thrown %s not an instance of %s",
caught.getClass().getName(), expected.getName()));
}
/**
* A sequential sized stream of ints generates the given number of values
*/
public void testIntsCount() {
LongAdder counter = new LongAdder();
Random r = new Random();
long size = 0;
for (int reps = 0; reps < REPS; ++reps) {
counter.reset();
r.ints(size).forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
size += 524959;
}
}
/**
* A sequential sized stream of longs generates the given number of values
*/
public void testLongsCount() {
LongAdder counter = new LongAdder();
Random r = new Random();
long size = 0;
for (int reps = 0; reps < REPS; ++reps) {
counter.reset();
r.longs(size).forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
size += 524959;
}
}
/**
* A sequential sized stream of doubles generates the given number of values
*/
public void testDoublesCount() {
LongAdder counter = new LongAdder();
Random r = new Random();
long size = 0;
for (int reps = 0; reps < REPS; ++reps) {
counter.reset();
r.doubles(size).forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
size += 524959;
}
}
/**
* Each of a sequential sized stream of bounded ints is within bounds
*/
public void testBoundedInts() {
AtomicInteger fails = new AtomicInteger(0);
Random r = new Random();
long size = 12345L;
for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
final int lo = least, hi = bound;
r.ints(size, lo, hi).
forEach(x -> {
if (x < lo || x >= hi)
fails.getAndIncrement();
});
}
}
assertEquals(fails.get(), 0);
}
/**
* Each of a sequential sized stream of bounded longs is within bounds
*/
public void testBoundedLongs() {
AtomicInteger fails = new AtomicInteger(0);
Random r = new Random();
long size = 123L;
for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
final long lo = least, hi = bound;
r.longs(size, lo, hi).
forEach(x -> {
if (x < lo || x >= hi)
fails.getAndIncrement();
});
}
}
assertEquals(fails.get(), 0);
}
/**
* Each of a sequential sized stream of bounded doubles is within bounds
*/
public void testBoundedDoubles() {
AtomicInteger fails = new AtomicInteger(0);
Random r = new Random();
long size = 456;
for (double least = 0.00011; least < 1.0e20; least *= 9) {
for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
final double lo = least, hi = bound;
r.doubles(size, lo, hi).
forEach(x -> {
if (x < lo || x >= hi)
fails.getAndIncrement();
});
}
}
assertEquals(fails.get(), 0);
}
/**
* A parallel unsized stream of ints generates at least 100 values
*/
public void testUnsizedIntsCount() {
LongAdder counter = new LongAdder();
Random r = new Random();
long size = 100;
r.ints().limit(size).parallel().forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
/**
* A parallel unsized stream of longs generates at least 100 values
*/
public void testUnsizedLongsCount() {
LongAdder counter = new LongAdder();
Random r = new Random();
long size = 100;
r.longs().limit(size).parallel().forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
/**
* A parallel unsized stream of doubles generates at least 100 values
*/
public void testUnsizedDoublesCount() {
LongAdder counter = new LongAdder();
Random r = new Random();
long size = 100;
r.doubles().limit(size).parallel().forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
/**
* A sequential unsized stream of ints generates at least 100 values
*/
public void testUnsizedIntsCountSeq() {
LongAdder counter = new LongAdder();
Random r = new Random();
long size = 100;
r.ints().limit(size).forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
/**
* A sequential unsized stream of longs generates at least 100 values
*/
public void testUnsizedLongsCountSeq() {
LongAdder counter = new LongAdder();
Random r = new Random();
long size = 100;
r.longs().limit(size).forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
/**
* A sequential unsized stream of doubles generates at least 100 values
*/
public void testUnsizedDoublesCountSeq() {
LongAdder counter = new LongAdder();
Random r = new Random();
long size = 100;
r.doubles().limit(size).forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
}
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.SplittableRandom;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.BiConsumer;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.AssertJUnit.assertTrue;
/**
* @test
* @run testng SplittableRandomTest
* @run testng/othervm -Djava.util.secureRandomSeed=true SplittableRandomTest
* @summary test methods on SplittableRandom
*/
@Test
public class SplittableRandomTest {
// Note: this test was copied from the 166 TCK SplittableRandomTest test
// and modified to be a TestNG test
/*
* Testing coverage notes:
*
* 1. Many of the test methods are adapted from ThreadLocalRandomTest.
*
* 2. These tests do not check for random number generator quality.
* But we check for minimal API compliance by requiring that
* repeated calls to nextX methods, up to NCALLS tries, produce at
* least two distinct results. (In some possible universe, a
* "correct" implementation might fail, but the odds are vastly
* less than that of encountering a hardware failure while running
* the test.) For bounded nextX methods, we sample various
* intervals across multiples of primes. In other tests, we repeat
* under REPS different values.
*/
// max numbers of calls to detect getting stuck on one value
static final int NCALLS = 10000;
// max sampled int bound
static final int MAX_INT_BOUND = (1 << 28);
// max sampled long bound
static final long MAX_LONG_BOUND = (1L << 42);
// Number of replications for other checks
static final int REPS = 20;
/**
* Repeated calls to nextInt produce at least two distinct results
*/
public void testNextInt() {
SplittableRandom sr = new SplittableRandom();
int f = sr.nextInt();
int i = 0;
while (i < NCALLS && sr.nextInt() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextLong produce at least two distinct results
*/
public void testNextLong() {
SplittableRandom sr = new SplittableRandom();
long f = sr.nextLong();
int i = 0;
while (i < NCALLS && sr.nextLong() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextDouble produce at least two distinct results
*/
public void testNextDouble() {
SplittableRandom sr = new SplittableRandom();
double f = sr.nextDouble();
int i = 0;
while (i < NCALLS && sr.nextDouble() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Two SplittableRandoms created with the same seed produce the
* same values for nextLong.
*/
public void testSeedConstructor() {
for (long seed = 2; seed < MAX_LONG_BOUND; seed += 15485863) {
SplittableRandom sr1 = new SplittableRandom(seed);
SplittableRandom sr2 = new SplittableRandom(seed);
for (int i = 0; i < REPS; ++i)
assertEquals(sr1.nextLong(), sr2.nextLong());
}
}
/**
* A SplittableRandom produced by split() of a default-constructed
* SplittableRandom generates a different sequence
*/
public void testSplit1() {
SplittableRandom sr = new SplittableRandom();
for (int reps = 0; reps < REPS; ++reps) {
SplittableRandom sc = sr.split();
int i = 0;
while (i < NCALLS && sr.nextLong() == sc.nextLong())
++i;
assertTrue(i < NCALLS);
}
}
/**
* A SplittableRandom produced by split() of a seeded-constructed
* SplittableRandom generates a different sequence
*/
public void testSplit2() {
SplittableRandom sr = new SplittableRandom(12345);
for (int reps = 0; reps < REPS; ++reps) {
SplittableRandom sc = sr.split();
int i = 0;
while (i < NCALLS && sr.nextLong() == sc.nextLong())
++i;
assertTrue(i < NCALLS);
}
}
/**
* nextInt(negative) throws IllegalArgumentException
*/
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNextIntBoundedNeg() {
SplittableRandom sr = new SplittableRandom();
int f = sr.nextInt(-17);
}
/**
* nextInt(least >= bound) throws IllegalArgumentException
*/
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNextIntBadBounds() {
SplittableRandom sr = new SplittableRandom();
int f = sr.nextInt(17, 2);
}
/**
* nextInt(bound) returns 0 <= value < bound;
* repeated calls produce at least two distinct results
*/
public void testNextIntBounded() {
SplittableRandom sr = new SplittableRandom();
// sample bound space across prime number increments
for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
int f = sr.nextInt(bound);
assertTrue(0 <= f && f < bound);
int i = 0;
int j;
while (i < NCALLS &&
(j = sr.nextInt(bound)) == f) {
assertTrue(0 <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
/**
* nextInt(least, bound) returns least <= value < bound;
* repeated calls produce at least two distinct results
*/
public void testNextIntBounded2() {
SplittableRandom sr = new SplittableRandom();
for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) {
for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) {
int f = sr.nextInt(least, bound);
assertTrue(least <= f && f < bound);
int i = 0;
int j;
while (i < NCALLS &&
(j = sr.nextInt(least, bound)) == f) {
assertTrue(least <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
}
/**
* nextLong(negative) throws IllegalArgumentException
*/
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNextLongBoundedNeg() {
SplittableRandom sr = new SplittableRandom();
long f = sr.nextLong(-17);
}
/**
* nextLong(least >= bound) throws IllegalArgumentException
*/
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNextLongBadBounds() {
SplittableRandom sr = new SplittableRandom();
long f = sr.nextLong(17, 2);
}
/**
* nextLong(bound) returns 0 <= value < bound;
* repeated calls produce at least two distinct results
*/
public void testNextLongBounded() {
SplittableRandom sr = new SplittableRandom();
for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) {
long f = sr.nextLong(bound);
assertTrue(0 <= f && f < bound);
int i = 0;
long j;
while (i < NCALLS &&
(j = sr.nextLong(bound)) == f) {
assertTrue(0 <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
/**
* nextLong(least, bound) returns least <= value < bound;
* repeated calls produce at least two distinct results
*/
public void testNextLongBounded2() {
SplittableRandom sr = new SplittableRandom();
for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) {
for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
long f = sr.nextLong(least, bound);
assertTrue(least <= f && f < bound);
int i = 0;
long j;
while (i < NCALLS &&
(j = sr.nextLong(least, bound)) == f) {
assertTrue(least <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
}
/**
* nextDouble(bound) throws IllegalArgumentException
*/
public void testNextDoubleBadBound() {
SplittableRandom sr = new SplittableRandom();
executeAndCatchIAE(() -> sr.nextDouble(0.0));
executeAndCatchIAE(() -> sr.nextDouble(-0.0));
executeAndCatchIAE(() -> sr.nextDouble(+0.0));
executeAndCatchIAE(() -> sr.nextDouble(-1.0));
executeAndCatchIAE(() -> sr.nextDouble(Double.NaN));
executeAndCatchIAE(() -> sr.nextDouble(Double.NEGATIVE_INFINITY));
// Returns Double.MAX_VALUE
// executeAndCatchIAE(() -> r.nextDouble(Double.POSITIVE_INFINITY));
}
/**
* nextDouble(origin, bound) throws IllegalArgumentException
*/
public void testNextDoubleBadOriginBound() {
testDoubleBadOriginBound(new SplittableRandom()::nextDouble);
}
// An arbitrary finite double value
static final double FINITE = Math.PI;
void testDoubleBadOriginBound(BiConsumer<Double, Double> bi) {
executeAndCatchIAE(() -> bi.accept(17.0, 2.0));
executeAndCatchIAE(() -> bi.accept(0.0, 0.0));
executeAndCatchIAE(() -> bi.accept(Double.NaN, FINITE));
executeAndCatchIAE(() -> bi.accept(FINITE, Double.NaN));
executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
// Returns NaN
// executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, FINITE));
// executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
executeAndCatchIAE(() -> bi.accept(FINITE, Double.NEGATIVE_INFINITY));
// Returns Double.MAX_VALUE
// executeAndCatchIAE(() -> bi.accept(FINITE, Double.POSITIVE_INFINITY));
executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, FINITE));
executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
}
/**
* nextDouble(least, bound) returns least <= value < bound;
* repeated calls produce at least two distinct results
*/
public void testNextDoubleBounded2() {
SplittableRandom sr = new SplittableRandom();
for (double least = 0.0001; least < 1.0e20; least *= 8) {
for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) {
double f = sr.nextDouble(least, bound);
assertTrue(least <= f && f < bound);
int i = 0;
double j;
while (i < NCALLS &&
(j = sr.nextDouble(least, bound)) == f) {
assertTrue(least <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
}
/**
* Invoking sized ints, long, doubles, with negative sizes throws
* IllegalArgumentException
*/
public void testBadStreamSize() {
SplittableRandom r = new SplittableRandom();
executeAndCatchIAE(() -> r.ints(-1L));
executeAndCatchIAE(() -> r.ints(-1L, 2, 3));
executeAndCatchIAE(() -> r.longs(-1L));
executeAndCatchIAE(() -> r.longs(-1L, -1L, 1L));
executeAndCatchIAE(() -> r.doubles(-1L));
executeAndCatchIAE(() -> r.doubles(-1L, .5, .6));
}
/**
* Invoking bounded ints, long, doubles, with illegal bounds throws
* IllegalArgumentException
*/
public void testBadStreamBounds() {
SplittableRandom r = new SplittableRandom();
executeAndCatchIAE(() -> r.ints(2, 1));
executeAndCatchIAE(() -> r.ints(10, 42, 42));
executeAndCatchIAE(() -> r.longs(-1L, -1L));
executeAndCatchIAE(() -> r.longs(10, 1L, -2L));
testDoubleBadOriginBound((o, b) -> r.doubles(10, o, b));
}
private void executeAndCatchIAE(Runnable r) {
executeAndCatch(IllegalArgumentException.class, r);
}
private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
Exception caught = null;
try {
r.run();
}
catch (Exception e) {
caught = e;
}
assertNotNull(caught,
String.format("No Exception was thrown, expected an Exception of %s to be thrown",
expected.getName()));
Assert.assertTrue(expected.isInstance(caught),
String.format("Exception thrown %s not an instance of %s",
caught.getClass().getName(), expected.getName()));
}
/**
* A parallel sized stream of ints generates the given number of values
*/
public void testIntsCount() {
LongAdder counter = new LongAdder();
SplittableRandom r = new SplittableRandom();
long size = 0;
for (int reps = 0; reps < REPS; ++reps) {
counter.reset();
r.ints(size).parallel().forEach(x -> {counter.increment();});
assertEquals(counter.sum(), size);
size += 524959;
}
}
/**
* A parallel sized stream of longs generates the given number of values
*/
public void testLongsCount() {
LongAdder counter = new LongAdder();
SplittableRandom r = new SplittableRandom();
long size = 0;
for (int reps = 0; reps < REPS; ++reps) {
counter.reset();
r.longs(size).parallel().forEach(x -> {counter.increment();});
assertEquals(counter.sum(), size);
size += 524959;
}
}
/**
* A parallel sized stream of doubles generates the given number of values
*/
public void testDoublesCount() {
LongAdder counter = new LongAdder();
SplittableRandom r = new SplittableRandom();
long size = 0;
for (int reps = 0; reps < REPS; ++reps) {
counter.reset();
r.doubles(size).parallel().forEach(x -> {counter.increment();});
assertEquals(counter.sum(), size);
size += 524959;
}
}
/**
* Each of a parallel sized stream of bounded ints is within bounds
*/
public void testBoundedInts() {
AtomicInteger fails = new AtomicInteger(0);
SplittableRandom r = new SplittableRandom();
long size = 12345L;
for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
final int lo = least, hi = bound;
r.ints(size, lo, hi).parallel().
forEach(x -> {if (x < lo || x >= hi)
fails.getAndIncrement(); });
}
}
assertEquals(fails.get(), 0);
}
/**
* Each of a parallel sized stream of bounded longs is within bounds
*/
public void testBoundedLongs() {
AtomicInteger fails = new AtomicInteger(0);
SplittableRandom r = new SplittableRandom();
long size = 123L;
for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
final long lo = least, hi = bound;
r.longs(size, lo, hi).parallel().
forEach(x -> {if (x < lo || x >= hi)
fails.getAndIncrement(); });
}
}
assertEquals(fails.get(), 0);
}
/**
* Each of a parallel sized stream of bounded doubles is within bounds
*/
public void testBoundedDoubles() {
AtomicInteger fails = new AtomicInteger(0);
SplittableRandom r = new SplittableRandom();
long size = 456;
for (double least = 0.00011; least < 1.0e20; least *= 9) {
for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
final double lo = least, hi = bound;
r.doubles(size, lo, hi).parallel().
forEach(x -> {if (x < lo || x >= hi)
fails.getAndIncrement(); });
}
}
assertEquals(fails.get(), 0);
}
/**
* A parallel unsized stream of ints generates at least 100 values
*/
public void testUnsizedIntsCount() {
LongAdder counter = new LongAdder();
SplittableRandom r = new SplittableRandom();
long size = 100;
r.ints().limit(size).parallel().forEach(x -> {counter.increment();});
assertEquals(counter.sum(), size);
}
/**
* A parallel unsized stream of longs generates at least 100 values
*/
public void testUnsizedLongsCount() {
LongAdder counter = new LongAdder();
SplittableRandom r = new SplittableRandom();
long size = 100;
r.longs().limit(size).parallel().forEach(x -> {counter.increment();});
assertEquals(counter.sum(), size);
}
/**
* A parallel unsized stream of doubles generates at least 100 values
*/
public void testUnsizedDoublesCount() {
LongAdder counter = new LongAdder();
SplittableRandom r = new SplittableRandom();
long size = 100;
r.doubles().limit(size).parallel().forEach(x -> {counter.increment();});
assertEquals(counter.sum(), size);
}
/**
* A sequential unsized stream of ints generates at least 100 values
*/
public void testUnsizedIntsCountSeq() {
LongAdder counter = new LongAdder();
SplittableRandom r = new SplittableRandom();
long size = 100;
r.ints().limit(size).forEach(x -> {counter.increment();});
assertEquals(counter.sum(), size);
}
/**
* A sequential unsized stream of longs generates at least 100 values
*/
public void testUnsizedLongsCountSeq() {
LongAdder counter = new LongAdder();
SplittableRandom r = new SplittableRandom();
long size = 100;
r.longs().limit(size).forEach(x -> {counter.increment();});
assertEquals(counter.sum(), size);
}
/**
* A sequential unsized stream of doubles generates at least 100 values
*/
public void testUnsizedDoublesCountSeq() {
LongAdder counter = new LongAdder();
SplittableRandom r = new SplittableRandom();
long size = 100;
r.doubles().limit(size).forEach(x -> {counter.increment();});
assertEquals(counter.sum(), size);
}
}
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import org.testng.Assert;
import org.testng.annotations.Test;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.BiConsumer;
import static org.testng.Assert.*;
/**
* @test
* @run testng ThreadLocalRandomTest
* @summary test methods on ThreadLocalRandom
*/
@Test
public class ThreadLocalRandomTest {
// Note: this test was copied from the 166 TCK ThreadLocalRandomTest test
// and modified to be a TestNG test
/*
* Testing coverage notes:
*
* We don't test randomness properties, but only that repeated
* calls, up to NCALLS tries, produce at least one different
* result. For bounded versions, we sample various intervals
* across multiples of primes.
*/
// max numbers of calls to detect getting stuck on one value
static final int NCALLS = 10000;
// max sampled int bound
static final int MAX_INT_BOUND = (1 << 28);
// max sampled long bound
static final long MAX_LONG_BOUND = (1L << 42);
// Number of replications for other checks
static final int REPS = 20;
/**
* setSeed throws UnsupportedOperationException
*/
@Test(expectedExceptions = UnsupportedOperationException.class)
public void testSetSeed() {
ThreadLocalRandom.current().setSeed(17);
}
/**
* Repeated calls to nextInt produce at least two distinct results
*/
public void testNextInt() {
int f = ThreadLocalRandom.current().nextInt();
int i = 0;
while (i < NCALLS && ThreadLocalRandom.current().nextInt() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextLong produce at least two distinct results
*/
public void testNextLong() {
long f = ThreadLocalRandom.current().nextLong();
int i = 0;
while (i < NCALLS && ThreadLocalRandom.current().nextLong() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextBoolean produce at least two distinct results
*/
public void testNextBoolean() {
boolean f = ThreadLocalRandom.current().nextBoolean();
int i = 0;
while (i < NCALLS && ThreadLocalRandom.current().nextBoolean() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextFloat produce at least two distinct results
*/
public void testNextFloat() {
float f = ThreadLocalRandom.current().nextFloat();
int i = 0;
while (i < NCALLS && ThreadLocalRandom.current().nextFloat() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextDouble produce at least two distinct results
*/
public void testNextDouble() {
double f = ThreadLocalRandom.current().nextDouble();
int i = 0;
while (i < NCALLS && ThreadLocalRandom.current().nextDouble() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* Repeated calls to nextGaussian produce at least two distinct results
*/
public void testNextGaussian() {
double f = ThreadLocalRandom.current().nextGaussian();
int i = 0;
while (i < NCALLS && ThreadLocalRandom.current().nextGaussian() == f)
++i;
assertTrue(i < NCALLS);
}
/**
* nextInt(negative) throws IllegalArgumentException
*/
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNextIntBoundedNeg() {
int f = ThreadLocalRandom.current().nextInt(-17);
}
/**
* nextInt(least >= bound) throws IllegalArgumentException
*/
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNextIntBadBounds() {
int f = ThreadLocalRandom.current().nextInt(17, 2);
}
/**
* nextInt(bound) returns 0 <= value < bound; repeated calls produce at
* least two distinct results
*/
public void testNextIntBounded() {
// sample bound space across prime number increments
for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
int f = ThreadLocalRandom.current().nextInt(bound);
assertTrue(0 <= f && f < bound);
int i = 0;
int j;
while (i < NCALLS &&
(j = ThreadLocalRandom.current().nextInt(bound)) == f) {
assertTrue(0 <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
/**
* nextInt(least, bound) returns least <= value < bound; repeated calls
* produce at least two distinct results
*/
public void testNextIntBounded2() {
for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) {
for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) {
int f = ThreadLocalRandom.current().nextInt(least, bound);
assertTrue(least <= f && f < bound);
int i = 0;
int j;
while (i < NCALLS &&
(j = ThreadLocalRandom.current().nextInt(least, bound)) == f) {
assertTrue(least <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
}
/**
* nextLong(negative) throws IllegalArgumentException
*/
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNextLongBoundedNeg() {
long f = ThreadLocalRandom.current().nextLong(-17);
}
/**
* nextLong(least >= bound) throws IllegalArgumentException
*/
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNextLongBadBounds() {
long f = ThreadLocalRandom.current().nextLong(17, 2);
}
/**
* nextLong(bound) returns 0 <= value < bound; repeated calls produce at
* least two distinct results
*/
public void testNextLongBounded() {
for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) {
long f = ThreadLocalRandom.current().nextLong(bound);
assertTrue(0 <= f && f < bound);
int i = 0;
long j;
while (i < NCALLS &&
(j = ThreadLocalRandom.current().nextLong(bound)) == f) {
assertTrue(0 <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
/**
* nextLong(least, bound) returns least <= value < bound; repeated calls
* produce at least two distinct results
*/
public void testNextLongBounded2() {
for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) {
for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
long f = ThreadLocalRandom.current().nextLong(least, bound);
assertTrue(least <= f && f < bound);
int i = 0;
long j;
while (i < NCALLS &&
(j = ThreadLocalRandom.current().nextLong(least, bound)) == f) {
assertTrue(least <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
}
/**
* nextDouble(bound) throws IllegalArgumentException
*/
public void testNextDoubleBadBound() {
ThreadLocalRandom r = ThreadLocalRandom.current();
executeAndCatchIAE(() -> r.nextDouble(0.0));
executeAndCatchIAE(() -> r.nextDouble(-0.0));
executeAndCatchIAE(() -> r.nextDouble(+0.0));
executeAndCatchIAE(() -> r.nextDouble(-1.0));
executeAndCatchIAE(() -> r.nextDouble(Double.NaN));
executeAndCatchIAE(() -> r.nextDouble(Double.NEGATIVE_INFINITY));
// Returns Double.MAX_VALUE
// executeAndCatchIAE(() -> r.nextDouble(Double.POSITIVE_INFINITY));
}
/**
* nextDouble(origin, bound) throws IllegalArgumentException
*/
public void testNextDoubleBadOriginBound() {
testDoubleBadOriginBound(ThreadLocalRandom.current()::nextDouble);
}
// An arbitrary finite double value
static final double FINITE = Math.PI;
void testDoubleBadOriginBound(BiConsumer<Double, Double> bi) {
executeAndCatchIAE(() -> bi.accept(17.0, 2.0));
executeAndCatchIAE(() -> bi.accept(0.0, 0.0));
executeAndCatchIAE(() -> bi.accept(Double.NaN, FINITE));
executeAndCatchIAE(() -> bi.accept(FINITE, Double.NaN));
executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY));
// Returns NaN
// executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, FINITE));
// executeAndCatchIAE(() -> bi.accept(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY));
executeAndCatchIAE(() -> bi.accept(FINITE, Double.NEGATIVE_INFINITY));
// Returns Double.MAX_VALUE
// executeAndCatchIAE(() -> bi.accept(FINITE, Double.POSITIVE_INFINITY));
executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY));
executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, FINITE));
executeAndCatchIAE(() -> bi.accept(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY));
}
/**
* nextDouble(least, bound) returns least <= value < bound; repeated calls
* produce at least two distinct results
*/
public void testNextDoubleBounded2() {
for (double least = 0.0001; least < 1.0e20; least *= 8) {
for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) {
double f = ThreadLocalRandom.current().nextDouble(least, bound);
assertTrue(least <= f && f < bound);
int i = 0;
double j;
while (i < NCALLS &&
(j = ThreadLocalRandom.current().nextDouble(least, bound)) == f) {
assertTrue(least <= j && j < bound);
++i;
}
assertTrue(i < NCALLS);
}
}
}
/**
* Invoking sized ints, long, doubles, with negative sizes throws
* IllegalArgumentException
*/
public void testBadStreamSize() {
ThreadLocalRandom r = ThreadLocalRandom.current();
executeAndCatchIAE(() -> r.ints(-1L));
executeAndCatchIAE(() -> r.ints(-1L, 2, 3));
executeAndCatchIAE(() -> r.longs(-1L));
executeAndCatchIAE(() -> r.longs(-1L, -1L, 1L));
executeAndCatchIAE(() -> r.doubles(-1L));
executeAndCatchIAE(() -> r.doubles(-1L, .5, .6));
}
/**
* Invoking bounded ints, long, doubles, with illegal bounds throws
* IllegalArgumentException
*/
public void testBadStreamBounds() {
ThreadLocalRandom r = ThreadLocalRandom.current();
executeAndCatchIAE(() -> r.ints(2, 1));
executeAndCatchIAE(() -> r.ints(10, 42, 42));
executeAndCatchIAE(() -> r.longs(-1L, -1L));
executeAndCatchIAE(() -> r.longs(10, 1L, -2L));
testDoubleBadOriginBound((o, b) -> r.doubles(10, o, b));
}
private void executeAndCatchIAE(Runnable r) {
executeAndCatch(IllegalArgumentException.class, r);
}
private void executeAndCatch(Class<? extends Exception> expected, Runnable r) {
Exception caught = null;
try {
r.run();
}
catch (Exception e) {
caught = e;
}
assertNotNull(caught,
String.format("No Exception was thrown, expected an Exception of %s to be thrown",
expected.getName()));
Assert.assertTrue(expected.isInstance(caught),
String.format("Exception thrown %s not an instance of %s",
caught.getClass().getName(), expected.getName()));
}
/**
* A parallel sized stream of ints generates the given number of values
*/
public void testIntsCount() {
LongAdder counter = new LongAdder();
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 0;
for (int reps = 0; reps < REPS; ++reps) {
counter.reset();
r.ints(size).parallel().forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
size += 524959;
}
}
/**
* A parallel sized stream of longs generates the given number of values
*/
public void testLongsCount() {
LongAdder counter = new LongAdder();
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 0;
for (int reps = 0; reps < REPS; ++reps) {
counter.reset();
r.longs(size).parallel().forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
size += 524959;
}
}
/**
* A parallel sized stream of doubles generates the given number of values
*/
public void testDoublesCount() {
LongAdder counter = new LongAdder();
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 0;
for (int reps = 0; reps < REPS; ++reps) {
counter.reset();
r.doubles(size).parallel().forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
size += 524959;
}
}
/**
* Each of a parallel sized stream of bounded ints is within bounds
*/
public void testBoundedInts() {
AtomicInteger fails = new AtomicInteger(0);
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 12345L;
for (int least = -15485867; least < MAX_INT_BOUND; least += 524959) {
for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 67867967) {
final int lo = least, hi = bound;
r.ints(size, lo, hi).parallel().
forEach(x -> {
if (x < lo || x >= hi)
fails.getAndIncrement();
});
}
}
assertEquals(fails.get(), 0);
}
/**
* Each of a parallel sized stream of bounded longs is within bounds
*/
public void testBoundedLongs() {
AtomicInteger fails = new AtomicInteger(0);
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 123L;
for (long least = -86028121; least < MAX_LONG_BOUND; least += 1982451653L) {
for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
final long lo = least, hi = bound;
r.longs(size, lo, hi).parallel().
forEach(x -> {
if (x < lo || x >= hi)
fails.getAndIncrement();
});
}
}
assertEquals(fails.get(), 0);
}
/**
* Each of a parallel sized stream of bounded doubles is within bounds
*/
public void testBoundedDoubles() {
AtomicInteger fails = new AtomicInteger(0);
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 456;
for (double least = 0.00011; least < 1.0e20; least *= 9) {
for (double bound = least * 1.0011; bound < 1.0e20; bound *= 17) {
final double lo = least, hi = bound;
r.doubles(size, lo, hi).parallel().
forEach(x -> {
if (x < lo || x >= hi)
fails.getAndIncrement();
});
}
}
assertEquals(fails.get(), 0);
}
/**
* A parallel unsized stream of ints generates at least 100 values
*/
public void testUnsizedIntsCount() {
LongAdder counter = new LongAdder();
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 100;
r.ints().limit(size).parallel().forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
/**
* A parallel unsized stream of longs generates at least 100 values
*/
public void testUnsizedLongsCount() {
LongAdder counter = new LongAdder();
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 100;
r.longs().limit(size).parallel().forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
/**
* A parallel unsized stream of doubles generates at least 100 values
*/
public void testUnsizedDoublesCount() {
LongAdder counter = new LongAdder();
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 100;
r.doubles().limit(size).parallel().forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
/**
* A sequential unsized stream of ints generates at least 100 values
*/
public void testUnsizedIntsCountSeq() {
LongAdder counter = new LongAdder();
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 100;
r.ints().limit(size).forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
/**
* A sequential unsized stream of longs generates at least 100 values
*/
public void testUnsizedLongsCountSeq() {
LongAdder counter = new LongAdder();
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 100;
r.longs().limit(size).forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
/**
* A sequential unsized stream of doubles generates at least 100 values
*/
public void testUnsizedDoublesCountSeq() {
LongAdder counter = new LongAdder();
ThreadLocalRandom r = ThreadLocalRandom.current();
long size = 100;
r.doubles().limit(size).forEach(x -> {
counter.increment();
});
assertEquals(counter.sum(), size);
}
}
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @run main/othervm/timeout=60 ReadersUnlockAfterWriteUnlock
* @bug 8023234
* @summary StampedLock serializes readers on writer unlock
* @author Dmitry Chyuko
* @author Aleksey Shipilev
*/
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.StampedLock;
public class ReadersUnlockAfterWriteUnlock {
static final int RNUM = 2;
static final StampedLock sl = new StampedLock();
static volatile boolean isDone;
static CyclicBarrier iterationStart = new CyclicBarrier(RNUM + 1);
static CyclicBarrier readersHaveLocks = new CyclicBarrier(RNUM);
static CyclicBarrier writerHasLock = new CyclicBarrier(RNUM + 1);
static class Reader extends Thread {
final String name;
Reader(String name) {
super();
this.name = name;
}
public void run() {
while (!isDone && !isInterrupted()) {
try {
iterationStart.await();
writerHasLock.await();
long rs = sl.readLock();
// single reader blocks here indefinitely if readers
// are serialized
readersHaveLocks.await();
sl.unlockRead(rs);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
}
}
public static void main(String[] args) throws InterruptedException {
for (int r = 0 ; r < RNUM; ++r) {
new Reader("r" + r).start();
}
int i;
for (i = 0; i < 1024; ++i) {
try {
iterationStart.await();
long ws = sl.writeLock();
writerHasLock.await();
Thread.sleep(10);
sl.unlockWrite(ws);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
isDone = true;
}
}
......@@ -67,26 +67,26 @@ public class BasicTest {
};
public void testMaxBy() {
Comparator<People> cmp = Comparator.comparing((Function<People, String>) People::getFirstName);
Comparator<People> cmp = Comparator.comparing(People::getFirstName);
// lesser
assertSame(maxBy(cmp).apply(people[0], people[1]), people[1]);
// euqal
cmp = Comparator.comparing((Function<People, String>) People::getLastName);
cmp = Comparator.comparing(People::getLastName);
assertSame(maxBy(cmp).apply(people[0], people[1]), people[0]);
// greater
cmp = Comparator.comparing((ToIntFunction<People>) People::getAge);
cmp = Comparator.comparingInt(People::getAge);
assertSame(maxBy(cmp).apply(people[0], people[1]), people[0]);
}
public void testLesserOf() {
Comparator<People> cmp = Comparator.comparing((Function<People, String>) People::getFirstName);
public void testMinBy() {
Comparator<People> cmp = Comparator.comparing(People::getFirstName);
// lesser
assertSame(minBy(cmp).apply(people[0], people[1]), people[0]);
// euqal
cmp = Comparator.comparing((Function<People, String>) People::getLastName);
cmp = Comparator.comparing(People::getLastName);
assertSame(minBy(cmp).apply(people[0], people[1]), people[0]);
// greater
cmp = Comparator.comparing((ToIntFunction<People>) People::getAge);
cmp = Comparator.comparingInt(People::getAge);
assertSame(minBy(cmp).apply(people[0], people[1]), people[1]);
}
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
* @test
* @bug 8005899
* @build TestLogger testlogger.MyResource
* @run main/othervm TestLogger
* @run main/othervm -Dsecurity=on TestLogger
**/
public class TestLogger {
public static final String RESOURCE_BUNDLE = "testlogger.MyResource";
public static final String ORG_LOGGER = "org";
public static final String FOO_LOGGER = ORG_LOGGER + ".foo.Foo";
public static final String BAR_LOGGER = ORG_LOGGER + ".bar.Bar";
public static final String GEE_LOGGER = ORG_LOGGER + ".gee.Gee";
public static final String GEE_GEE_LOGGER = GEE_LOGGER+".Gee";
public static void main(String[] args) {
final String security = System.getProperty("security", "off");
System.out.println("Security is " + security);
if ("on".equals(security)) {
System.setSecurityManager(new SecurityManager());
}
newLogger(FOO_LOGGER, RESOURCE_BUNDLE);
newLogger(FOO_LOGGER);
newLogger(BAR_LOGGER);
newLogger(BAR_LOGGER, RESOURCE_BUNDLE);
newLogger(GEE_LOGGER, null);
newLogger(GEE_LOGGER, RESOURCE_BUNDLE);
newLogger(ORG_LOGGER);
newLogger(GEE_GEE_LOGGER);
for (String log : new String[] { FOO_LOGGER, BAR_LOGGER, GEE_LOGGER }) {
if (!RESOURCE_BUNDLE.equals(Logger.getLogger(log).getResourceBundleName())) {
throw new RuntimeException("Shouldn't allow to reset the resource bundle for " + log);
}
try {
Logger logger = Logger.getLogger(log, null);
if (!RESOURCE_BUNDLE.equals(logger.getResourceBundleName())) {
throw new RuntimeException("Shouldn't allow to reset the resource bundle for " + log);
}
throw new RuntimeException("Expected IllegalArgumentException not thrown for " + log);
} catch (IllegalArgumentException e) {
System.out.println("Got expected exception for " + log +": " + e);
}
}
for (String log : new String[] { ORG_LOGGER, GEE_GEE_LOGGER }) {
if (Logger.getLogger(log).getResourceBundleName() != null) {
throw new RuntimeException("Resource bundle is not null for log: "
+ Logger.getLogger(log).getResourceBundleName());
}
try {
Logger logger = Logger.getLogger(log, null);
if (logger.getResourceBundleName() != null) {
throw new RuntimeException("Resource bundle is not null for log: "
+ logger.getResourceBundleName());
}
System.out.println("Success calling Logger.getLogger(\""+log+"\", null)");
} catch (IllegalArgumentException e) {
throw new RuntimeException("Unexpected exception for " + log +": " + e, e);
}
}
}
private static List<Logger> strongRefs = new ArrayList<>();
private static void newLogger(String name) {
strongRefs.add(Logger.getLogger(name));
}
private static void newLogger(String name, String resourceBundleName) {
strongRefs.add(Logger.getLogger(name, resourceBundleName));
}
}
/*
* Copyright (c) 1996, 1997, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
......@@ -22,25 +20,33 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package testlogger;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;
/**
* Compare: an interface to enable users to define the result of
* a comparison of two objects.
*
* @author Sunita Mani
* A dummy resource bundle for testing purposes.
* @author danielfuchs
*/
public class MyResource extends ResourceBundle {
Map<String, Object> bundle = new HashMap<>();
package sun.misc;
public interface Compare {
@Override
protected Object handleGetObject(String key) {
bundle.put(key,"Localized: " + key);
return bundle.get(key);
}
/**
* doCompare
*
* @param obj1 first object to compare.
* @param obj2 second object to compare.
* @return -1 if obj1 < obj2, 0 if obj1 == obj2, 1 if obj1 > obj2.
*/
public int doCompare(Object obj1, Object obj2);
@Override
public Enumeration<String> getKeys() {
final Hashtable<String, Object> h = new Hashtable<>(bundle);
return h.keys();
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary Unit tests for wrapping classes should delegate to default methods
* @library ../stream/bootlib
* @build java.util.stream.OpTestCase
* @run testng/othervm PatternTest
*/
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.LambdaTestHelpers;
import java.util.stream.OpTestCase;
import java.util.stream.Stream;
import java.util.stream.TestData;
@Test
public class PatternTest extends OpTestCase {
@DataProvider(name = "Stream<String>")
public static Object[][] makeStreamTestData() {
List<Object[]> data = new ArrayList<>();
String description = "";
String input = "awgqwefg1fefw4vssv1vvv1";
Pattern pattern = Pattern.compile("4");
List<String> expected = new ArrayList<>();
expected.add("awgqwefg1fefw");
expected.add("vssv1vvv1");
// Must match the type signature of the consumer of this data, testStrings
// String, String, Pattern, List<String>
data.add(new Object[]{description, input, pattern, expected});
input = "afbfq\u00a3abgwgb\u00a3awngnwggw\u00a3a\u00a3ahjrnhneerh";
pattern = Pattern.compile("\u00a3a");
expected = new ArrayList<>();
expected.add("afbfq");
expected.add("bgwgb");
expected.add("wngnwggw");
expected.add("");
expected.add("hjrnhneerh");
data.add(new Object[]{description, input, pattern, expected});
input = "awgqwefg1fefw4vssv1vvv1";
pattern = Pattern.compile("1");
expected = new ArrayList<>();
expected.add("awgqwefg");
expected.add("fefw4vssv");
expected.add("vvv");
data.add(new Object[]{description, input, pattern, expected});
input = "a\u4ebafg1fefw\u4eba4\u9f9cvssv\u9f9c1v\u672c\u672cvv";
pattern = Pattern.compile("1");
expected = new ArrayList<>();
expected.add("a\u4ebafg");
expected.add("fefw\u4eba4\u9f9cvssv\u9f9c");
expected.add("v\u672c\u672cvv");
data.add(new Object[]{description, input, pattern, expected});
input = "1\u56da23\u56da456\u56da7890";
pattern = Pattern.compile("\u56da");
expected = new ArrayList<>();
expected.add("1");
expected.add("23");
expected.add("456");
expected.add("7890");
data.add(new Object[]{description, input, pattern, expected});
input = "1\u56da23\u9f9c\u672c\u672c\u56da456\u56da\u9f9c\u672c7890";
pattern = Pattern.compile("\u56da");
expected = new ArrayList<>();
expected.add("1");
expected.add("23\u9f9c\u672c\u672c");
expected.add("456");
expected.add("\u9f9c\u672c7890");
data.add(new Object[]{description, input, pattern, expected});
input = "";
pattern = Pattern.compile("\u56da");
expected = new ArrayList<>();
data.add(new Object[]{description, input, pattern, expected});
description = "Multiple separators";
input = "This is,testing: with\tdifferent separators.";
pattern = Pattern.compile("[ \t,:.]");
expected = new ArrayList<>();
expected.add("This");
expected.add("is");
expected.add("testing");
expected.add("");
expected.add("with");
expected.add("different");
expected.add("separators");
data.add(new Object[] {description, input, pattern, expected});
return data.toArray(new Object[0][]);
}
@Test(dataProvider = "Stream<String>")
public void testStrings(String description, String input, Pattern pattern, List<String> expected) {
Supplier<Stream<String>> ss = () -> pattern.splitAsStream(input);
withData(TestData.Factory.ofSupplier(description, ss))
.stream(LambdaTestHelpers.identity())
.expectedResult(expected)
.exercise();
}
}
......@@ -33,7 +33,7 @@
* 5013885 5003322 4988891 5098443 5110268 6173522 4829857 5027748 6376940
* 6358731 6178785 6284152 6231989 6497148 6486934 6233084 6504326 6635133
* 6350801 6676425 6878475 6919132 6931676 6948903 6990617 7014645 7039066
* 7067045 7014640 7189363 8007395 8013252 8013254 8012646
* 7067045 7014640 7189363 8007395 8013252 8013254 8012646 8023647
*/
import java.util.regex.*;
......@@ -146,6 +146,7 @@ public class RegExTest {
linebreakTest();
branchTest();
groupCurlyNotFoundSuppTest();
groupCurlyBackoffTest();
patternAsPredicate();
if (failure) {
throw new
......@@ -3999,6 +4000,15 @@ public class RegExTest {
report("GroupCurly NotFoundSupp");
}
// This test is for 8023647
private static void groupCurlyBackoffTest() throws Exception {
if (!"abc1c".matches("(\\w)+1\\1") ||
"abc11".matches("(\\w)+1\\1")) {
failCount++;
}
report("GroupCurly backoff");
}
// This test is for 8012646
private static void patternAsPredicate() throws Exception {
Predicate<String> p = Pattern.compile("[a-z]+").asPredicate();
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.tests.java.util;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Spliterator;
import java.util.SplittableRandom;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.DoubleStream;
import java.util.stream.DoubleStreamTestScenario;
import java.util.stream.IntStream;
import java.util.stream.IntStreamTestScenario;
import java.util.stream.LongStream;
import java.util.stream.LongStreamTestScenario;
import java.util.stream.OpTestCase;
import java.util.stream.StreamSupport;
import java.util.stream.TestData;
@Test
public class SplittableRandomTest extends OpTestCase {
static class RandomBoxedSpliterator<T> implements Spliterator<T> {
final SplittableRandom rng;
long index;
final long fence;
final Function<SplittableRandom, T> rngF;
RandomBoxedSpliterator(SplittableRandom rng, long index, long fence, Function<SplittableRandom, T> rngF) {
this.rng = rng;
this.index = index;
this.fence = fence;
this.rngF = rngF;
}
public RandomBoxedSpliterator<T> trySplit() {
long i = index, m = (i + fence) >>> 1;
return (m <= i) ? null :
new RandomBoxedSpliterator<>(rng.split(), i, index = m, rngF);
}
public long estimateSize() {
return fence - index;
}
public int characteristics() {
return (Spliterator.SIZED | Spliterator.SUBSIZED |
Spliterator.NONNULL | Spliterator.IMMUTABLE);
}
@Override
public boolean tryAdvance(Consumer<? super T> consumer) {
if (consumer == null) throw new NullPointerException();
long i = index, f = fence;
if (i < f) {
consumer.accept(rngF.apply(rng));
index = i + 1;
return true;
}
return false;
}
}
static final int SIZE = 1 << 16;
// Ensure there is a range of a power of 2
static final int[] BOUNDS = {256};
static final int[] ORIGINS = {-16, 0, 16};
static <T extends Comparable<T>> ResultAsserter<Iterable<T>> randomAsserter(int size, T origin, T bound) {
return (act, exp, ord, par) -> {
int count = 0;
Set<Comparable<T>> values = new HashSet<>();
for (Comparable<T> t : act) {
if (origin.compareTo(bound) < 0) {
assertTrue(t.compareTo(origin) >= 0);
assertTrue(t.compareTo(bound) < 0);
}
values.add(t);
count++;
}
assertEquals(count, size);
// Assert that at least one different result is produced
// For the size of the data it is highly improbable that this
// will cause a false negative (i.e. a false failure)
assertTrue(values.size() > 1);
};
}
@DataProvider(name = "ints")
public static Object[][] intsDataProvider() {
List<Object[]> data = new ArrayList<>();
// Function to create a stream using a RandomBoxedSpliterator
Function<Function<SplittableRandom, Integer>, IntStream> rbsf =
sf -> StreamSupport.stream(new RandomBoxedSpliterator<>(new SplittableRandom(), 0, SIZE, sf), false).
mapToInt(i -> i);
// Unbounded
data.add(new Object[]{
TestData.Factory.ofIntSupplier(
String.format("new SplittableRandom().ints().limit(%d)", SIZE),
() -> new SplittableRandom().ints().limit(SIZE)),
randomAsserter(SIZE, Integer.MAX_VALUE, 0)
});
data.add(new Object[]{
TestData.Factory.ofIntSupplier(
String.format("new SplittableRandom().ints(%d)", SIZE),
() -> new SplittableRandom().ints(SIZE)),
randomAsserter(SIZE, Integer.MAX_VALUE, 0)
});
data.add(new Object[]{
TestData.Factory.ofIntSupplier(
String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextInt())", SIZE),
() -> rbsf.apply(sr -> sr.nextInt())),
randomAsserter(SIZE, Integer.MAX_VALUE, 0)
});
// Bounded
for (int b : BOUNDS) {
for (int o : ORIGINS) {
final int origin = o;
final int bound = b;
data.add(new Object[]{
TestData.Factory.ofIntSupplier(
String.format("new SplittableRandom().ints(%d, %d).limit(%d)", origin, bound, SIZE),
() -> new SplittableRandom().ints(origin, bound).limit(SIZE)),
randomAsserter(SIZE, origin, bound)
});
data.add(new Object[]{
TestData.Factory.ofIntSupplier(
String.format("new SplittableRandom().ints(%d, %d, %d)", SIZE, origin, bound),
() -> new SplittableRandom().ints(SIZE, origin, bound)),
randomAsserter(SIZE, origin, bound)
});
if (origin == 0) {
data.add(new Object[]{
TestData.Factory.ofIntSupplier(
String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextInt(%d))", SIZE, bound),
() -> rbsf.apply(sr -> sr.nextInt(bound))),
randomAsserter(SIZE, origin, bound)
});
}
data.add(new Object[]{
TestData.Factory.ofIntSupplier(
String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextInt(%d, %d))", SIZE, origin, bound),
() -> rbsf.apply(sr -> sr.nextInt(origin, bound))),
randomAsserter(SIZE, origin, bound)
});
}
}
return data.toArray(new Object[0][]);
}
@Test(dataProvider = "ints")
public void testInts(TestData.OfInt data, ResultAsserter<Iterable<Integer>> ra) {
withData(data).
stream(s -> s).
without(IntStreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED).
resultAsserter(ra).
exercise();
}
@DataProvider(name = "longs")
public static Object[][] longsDataProvider() {
List<Object[]> data = new ArrayList<>();
// Function to create a stream using a RandomBoxedSpliterator
Function<Function<SplittableRandom, Long>, LongStream> rbsf =
sf -> StreamSupport.stream(new RandomBoxedSpliterator<>(new SplittableRandom(), 0, SIZE, sf), false).
mapToLong(i -> i);
// Unbounded
data.add(new Object[]{
TestData.Factory.ofLongSupplier(
String.format("new SplittableRandom().longs().limit(%d)", SIZE),
() -> new SplittableRandom().longs().limit(SIZE)),
randomAsserter(SIZE, Long.MAX_VALUE, 0L)
});
data.add(new Object[]{
TestData.Factory.ofLongSupplier(
String.format("new SplittableRandom().longs(%d)", SIZE),
() -> new SplittableRandom().longs(SIZE)),
randomAsserter(SIZE, Long.MAX_VALUE, 0L)
});
data.add(new Object[]{
TestData.Factory.ofLongSupplier(
String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextLong())", SIZE),
() -> rbsf.apply(sr -> sr.nextLong())),
randomAsserter(SIZE, Long.MAX_VALUE, 0L)
});
// Bounded
for (int b : BOUNDS) {
for (int o : ORIGINS) {
final long origin = o;
final long bound = b;
data.add(new Object[]{
TestData.Factory.ofLongSupplier(
String.format("new SplittableRandom().longs(%d, %d).limit(%d)", origin, bound, SIZE),
() -> new SplittableRandom().longs(origin, bound).limit(SIZE)),
randomAsserter(SIZE, origin, bound)
});
data.add(new Object[]{
TestData.Factory.ofLongSupplier(
String.format("new SplittableRandom().longs(%d, %d, %d)", SIZE, origin, bound),
() -> new SplittableRandom().longs(SIZE, origin, bound)),
randomAsserter(SIZE, origin, bound)
});
if (origin == 0) {
data.add(new Object[]{
TestData.Factory.ofLongSupplier(
String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextLong(%d))", SIZE, bound),
() -> rbsf.apply(sr -> sr.nextLong(bound))),
randomAsserter(SIZE, origin, bound)
});
}
data.add(new Object[]{
TestData.Factory.ofLongSupplier(
String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextLong(%d, %d))", SIZE, origin, bound),
() -> rbsf.apply(sr -> sr.nextLong(origin, bound))),
randomAsserter(SIZE, origin, bound)
});
}
}
return data.toArray(new Object[0][]);
}
@Test(dataProvider = "longs")
public void testLongs(TestData.OfLong data, ResultAsserter<Iterable<Long>> ra) {
withData(data).
stream(s -> s).
without(LongStreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED).
resultAsserter(ra).
exercise();
}
@DataProvider(name = "doubles")
public static Object[][] doublesDataProvider() {
List<Object[]> data = new ArrayList<>();
// Function to create a stream using a RandomBoxedSpliterator
Function<Function<SplittableRandom, Double>, DoubleStream> rbsf =
sf -> StreamSupport.stream(new RandomBoxedSpliterator<>(new SplittableRandom(), 0, SIZE, sf), false).
mapToDouble(i -> i);
// Unbounded
data.add(new Object[]{
TestData.Factory.ofDoubleSupplier(
String.format("new SplittableRandom().doubles().limit(%d)", SIZE),
() -> new SplittableRandom().doubles().limit(SIZE)),
randomAsserter(SIZE, Double.MAX_VALUE, 0d)
});
data.add(new Object[]{
TestData.Factory.ofDoubleSupplier(
String.format("new SplittableRandom().doubles(%d)", SIZE),
() -> new SplittableRandom().doubles(SIZE)),
randomAsserter(SIZE, Double.MAX_VALUE, 0d)
});
data.add(new Object[]{
TestData.Factory.ofDoubleSupplier(
String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextDouble())", SIZE),
() -> rbsf.apply(sr -> sr.nextDouble())),
randomAsserter(SIZE, Double.MAX_VALUE, 0d)
});
// Bounded
for (int b : BOUNDS) {
for (int o : ORIGINS) {
final double origin = o;
final double bound = b;
data.add(new Object[]{
TestData.Factory.ofDoubleSupplier(
String.format("new SplittableRandom().doubles(%f, %f).limit(%d)", origin, bound, SIZE),
() -> new SplittableRandom().doubles(origin, bound).limit(SIZE)),
randomAsserter(SIZE, origin, bound)
});
data.add(new Object[]{
TestData.Factory.ofDoubleSupplier(
String.format("new SplittableRandom().doubles(%d, %f, %f)", SIZE, origin, bound),
() -> new SplittableRandom().doubles(SIZE, origin, bound)),
randomAsserter(SIZE, origin, bound)
});
if (origin == 0) {
data.add(new Object[]{
TestData.Factory.ofDoubleSupplier(
String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextDouble(%f))", SIZE, bound),
() -> rbsf.apply(sr -> sr.nextDouble(bound))),
randomAsserter(SIZE, origin, bound)
});
}
data.add(new Object[]{
TestData.Factory.ofDoubleSupplier(
String.format("new RandomBoxedSpliterator(0, %d, sr -> sr.nextDouble(%f, %f))", SIZE, origin, bound),
() -> rbsf.apply(sr -> sr.nextDouble(origin, bound))),
randomAsserter(SIZE, origin, bound)
});
}
}
return data.toArray(new Object[0][]);
}
@Test(dataProvider = "doubles")
public void testDoubles(TestData.OfDouble data, ResultAsserter<Iterable<Double>> ra) {
withData(data).
stream(s -> s).
without(DoubleStreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED).
resultAsserter(ra).
exercise();
}
}
......@@ -23,7 +23,7 @@
/**
* @test
* @bug 4759491 6303183 7012868 8015666
* @bug 4759491 6303183 7012868 8015666 8023713
* @summary Test ZOS and ZIS timestamp in extra field correctly
*/
......@@ -32,6 +32,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.util.Arrays;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
......@@ -52,24 +53,26 @@ public class TestExtraTime {
FileTime ctime = FileTime.from(time - 300000, TimeUnit.MILLISECONDS);
TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
test(mtime, null, null, null);
for (byte[] extra : new byte[][] { null, new byte[] {1, 2, 3}}) {
test(mtime, null, null, null, extra);
// ms-dos 1980 epoch problem
test(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null);
test(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null, extra);
// non-default tz
test(mtime, null, null, tz);
test(mtime, null, null, tz, extra);
test(mtime, atime, null, null);
test(mtime, null, ctime, null);
test(mtime, atime, ctime, null);
test(mtime, atime, null, null, extra);
test(mtime, null, ctime, null, extra);
test(mtime, atime, ctime, null, extra);
test(mtime, atime, null, tz);
test(mtime, null, ctime, tz);
test(mtime, atime, ctime, tz);
test(mtime, atime, null, tz, extra);
test(mtime, null, ctime, tz, extra);
test(mtime, atime, ctime, tz, extra);
}
}
}
static void test(FileTime mtime, FileTime atime, FileTime ctime,
TimeZone tz) throws Throwable {
TimeZone tz, byte[] extra) throws Throwable {
System.out.printf("--------------------%nTesting: [%s]/[%s]/[%s]%n",
mtime, atime, ctime);
TimeZone tz0 = TimeZone.getDefault();
......@@ -78,8 +81,8 @@ public class TestExtraTime {
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
ZipEntry ze = new ZipEntry("TestExtreTime.java");
ZipEntry ze = new ZipEntry("TestExtraTime.java");
ze.setExtra(extra);
ze.setLastModifiedTime(mtime);
if (atime != null)
ze.setLastAccessTime(atime);
......@@ -87,6 +90,14 @@ public class TestExtraTime {
ze.setCreationTime(ctime);
zos.putNextEntry(ze);
zos.write(new byte[] { 1,2 ,3, 4});
// append an extra entry to help check if the length and data
// of the extra field are being correctly written (in previous
// entry).
if (extra != null) {
ze = new ZipEntry("TestExtraEntry");
zos.putNextEntry(ze);
}
zos.close();
if (tz != null) {
TimeZone.setDefault(tz0);
......@@ -96,23 +107,23 @@ public class TestExtraTime {
new ByteArrayInputStream(baos.toByteArray()));
ze = zis.getNextEntry();
zis.close();
check(mtime, atime, ctime, ze);
check(mtime, atime, ctime, ze, extra);
// ZipFile
Path zpath = Paths.get(System.getProperty("test.dir", "."),
"TestExtraTimp.zip");
"TestExtraTime.zip");
Files.copy(new ByteArrayInputStream(baos.toByteArray()), zpath);
ZipFile zf = new ZipFile(zpath.toFile());
ze = zf.getEntry("TestExtreTime.java");
ze = zf.getEntry("TestExtraTime.java");
// ZipFile read entry from cen, which does not have a/ctime,
// for now.
check(mtime, null, null, ze);
check(mtime, null, null, ze, extra);
zf.close();
Files.delete(zpath);
}
static void check(FileTime mtime, FileTime atime, FileTime ctime,
ZipEntry ze) {
ZipEntry ze, byte[] extra) {
/*
System.out.printf(" mtime [%tc]: [%tc]/[%tc]%n",
mtime.to(TimeUnit.MILLISECONDS),
......@@ -130,5 +141,17 @@ public class TestExtraTime {
ctime.to(TimeUnit.SECONDS) !=
ze.getCreationTime().to(TimeUnit.SECONDS))
throw new RuntimeException("Timestamp: storing ctime failed!");
if (extra != null) {
// if extra data exists, the current implementation put it at
// the end of the extra data array (implementation detail)
byte[] extra1 = ze.getExtra();
if (extra1 == null || extra1.length < extra.length ||
!Arrays.equals(Arrays.copyOfRange(extra1,
extra1.length - extra.length,
extra1.length),
extra)) {
throw new RuntimeException("Timestamp: storing extra field failed!");
}
}
}
}
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8015669
* @summary KerberosPrincipal::equals should ignore name-type
* @compile -XDignore.symbol.file KPEquals.java
* @run main/othervm KPEquals
*/
import sun.security.jgss.GSSUtil;
import javax.security.auth.kerberos.KerberosKey;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.kerberos.KeyTab;
public class KPEquals {
public static void main(String[] args) throws Exception {
new OneKDC(null).writeJAASConf();
Context c = Context.fromJAAS("client");
Context s = Context.fromThinAir();
KerberosPrincipal kp = new KerberosPrincipal(
OneKDC.SERVER + "@" + OneKDC.REALM,
KerberosPrincipal.KRB_NT_SRV_INST);
s.s().getPrincipals().add(kp);
for (KerberosKey k: KeyTab.getInstance(kp).getKeys(kp)) {
s.s().getPrivateCredentials().add(k);
}
c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
s.startAsServer(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
Context.handshake(c, s);
}
}
/*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -21,14 +21,16 @@
* questions.
*/
//
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
//
/*
* @test
* @bug 4366807
* @summary Need new APIs to get/set session timeout and session cache size.
* @run main/othervm SessionCacheSizeTests
*
* SunJSSE does not support dynamic system properties, no way to re-use
* system properties in samevm/agentvm mode.
*/
import java.io.*;
......@@ -113,7 +115,9 @@ public class SessionCacheSizeTests {
/*
* Signal Client, we're ready for his connect.
*/
if (createdPorts == serverPorts.length) {
serverReady = true;
}
int read = 0;
int nConnections = 0;
/*
......@@ -310,7 +314,6 @@ public class SessionCacheSizeTests {
* Fork off the other side, then do your work.
*/
SessionCacheSizeTests() throws Exception {
/*
* create the SSLServerSocket and SSLSocket factories
*/
......@@ -323,10 +326,12 @@ public class SessionCacheSizeTests {
int serverConns = MAX_ACTIVE_CONNECTIONS / (serverPorts.length);
int remainingConns = MAX_ACTIVE_CONNECTIONS % (serverPorts.length);
Exception startException = null;
try {
if (separateServerThread) {
for (int i = 0; i < serverPorts.length; i++) {
// distribute remaining connections among the available ports
// distribute remaining connections among the
// available ports
if (i < remainingConns)
startServer(serverPorts[i], (serverConns + 1), true);
else
......@@ -342,27 +347,66 @@ public class SessionCacheSizeTests {
startServer(serverPorts[i], serverConns, false);
}
}
} catch (Exception e) {
startException = e;
}
/*
* Wait for other side to close down.
*/
if (separateServerThread) {
if (serverThread != null) {
serverThread.join();
}
} else {
if (clientThread != null) {
clientThread.join();
}
}
/*
* When we get here, the test is pretty much over.
*
* If the main thread excepted, that propagates back
* immediately. If the other thread threw an exception, we
* should report back.
*/
if (serverException != null)
throw serverException;
if (clientException != null)
throw clientException;
Exception local;
Exception remote;
if (separateServerThread) {
remote = serverException;
local = clientException;
} else {
remote = clientException;
local = serverException;
}
Exception exception = null;
/*
* Check various exception conditions.
*/
if ((local != null) && (remote != null)) {
// If both failed, return the curthread's exception.
local.initCause(remote);
exception = local;
} else if (local != null) {
exception = local;
} else if (remote != null) {
exception = remote;
} else if (startException != null) {
exception = startException;
}
/*
* If there was an exception *AND* a startException,
* output it.
*/
if (exception != null) {
if (exception != startException && startException != null) {
exception.addSuppressed(startException);
}
throw exception;
}
// Fall-through: no exception to throw!
}
void startServer(final int port, final int nConns,
......@@ -387,7 +431,13 @@ public class SessionCacheSizeTests {
};
serverThread.start();
} else {
try {
doServerSide(port, nConns);
} catch (Exception e) {
serverException = e;
} finally {
serverReady = true;
}
}
}
......@@ -409,7 +459,11 @@ public class SessionCacheSizeTests {
};
clientThread.start();
} else {
try {
doClientSide();
} catch (Exception e) {
clientException = e;
}
}
}
}
/*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -21,14 +21,14 @@
* questions.
*/
// SunJSSE does not support dynamic system properties, no way to re-use
// system properties in samevm/agentvm mode.
/*
* @test
* @bug 4366807
* @summary Need new APIs to get/set session timeout and session cache size.
* @run main/othervm SessionTimeOutTests
*
* SunJSSE does not support dynamic system properties, no way to re-use
* system properties in samevm/agentvm mode.
*/
import java.io.*;
......@@ -348,9 +348,12 @@ public class SessionTimeOutTests {
int serverConns = MAX_ACTIVE_CONNECTIONS / (serverPorts.length);
int remainingConns = MAX_ACTIVE_CONNECTIONS % (serverPorts.length);
Exception startException = null;
try {
if (separateServerThread) {
for (int i = 0; i < serverPorts.length; i++) {
// distribute remaining connections among the available ports
// distribute remaining connections among the
// vailable ports
if (i < remainingConns)
startServer(serverPorts[i], (serverConns + 1), true);
else
......@@ -366,27 +369,67 @@ public class SessionTimeOutTests {
startServer(serverPorts[i], serverConns, false);
}
}
} catch (Exception e) {
startException = e;
}
/*
* Wait for other side to close down.
*/
if (separateServerThread) {
if (serverThread != null) {
serverThread.join();
}
} else {
if (clientThread != null) {
clientThread.join();
}
}
/*
* When we get here, the test is pretty much over.
*
* If the main thread excepted, that propagates back
* immediately. If the other thread threw an exception, we
* should report back.
* Which side threw the error?
*/
Exception local;
Exception remote;
if (separateServerThread) {
remote = serverException;
local = clientException;
} else {
remote = clientException;
local = serverException;
}
Exception exception = null;
/*
* Check various exception conditions.
*/
if (serverException != null)
throw serverException;
if (clientException != null)
throw clientException;
if ((local != null) && (remote != null)) {
// If both failed, return the curthread's exception.
local.initCause(remote);
exception = local;
} else if (local != null) {
exception = local;
} else if (remote != null) {
exception = remote;
} else if (startException != null) {
exception = startException;
}
/*
* If there was an exception *AND* a startException,
* output it.
*/
if (exception != null) {
if (exception != startException && startException != null) {
exception.addSuppressed(startException);
}
throw exception;
}
// Fall-through: no exception to throw!
}
void startServer(final int port, final int nConns,
......@@ -411,7 +454,13 @@ public class SessionTimeOutTests {
};
serverThread.start();
} else {
try {
doServerSide(port, nConns);
} catch (Exception e) {
serverException = e;
} finally {
serverReady = 0;
}
}
}
......@@ -433,7 +482,11 @@ public class SessionTimeOutTests {
};
clientThread.start();
} else {
try {
doClientSide();
} catch (Exception e) {
clientException = e;
}
}
}
}
......@@ -243,7 +243,7 @@ public class SSLSocketTemplate {
* output it.
*/
if (exception != null) {
if (exception != startException) {
if (exception != startException && startException != null) {
exception.addSuppressed(startException);
}
throw exception;
......
#
# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# @test
# @bug 8022761
# @summary regression: SecurityException is NOT thrown while trying to pack a wrongly signed Indexed Jar file
#
if [ "${TESTJAVA}" = "" ] ; then
JAVAC_CMD=`which javac`
TESTJAVA=`dirname $JAVAC_CMD`/..
fi
# set platform-dependent variables
OS=`uname -s`
case "$OS" in
Windows_* )
FS="\\"
;;
* )
FS="/"
;;
esac
F=abcde
KS=jvindex.jks
JFILE=jvindex.jar
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \
-keystore $KS"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit"
rm $F $KS $JFILE 2> /dev/null
echo 12345 > $F
$JAR cvf $JFILE $F
ERR=""
$KT -alias a -dname CN=a -genkey -validity 300 || ERR="$ERR 1"
$JARSIGNER $JFILE a || ERR="$ERR 2"
$JAR i $JFILE
# Make sure the $F line has "sm" (signed and in manifest)
$JARSIGNER -verify -verbose $JFILE | grep $F | grep sm || ERR="$ERR 3"
if [ "$ERR" = "" ]; then
exit 0
else
echo "ERR is $ERR"
exit 1
fi
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册