--- a/jdk/make/com/sun/security/auth/FILES_java.gmk Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/make/com/sun/security/auth/FILES_java.gmk Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
#
-# 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 @@
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
--- a/jdk/makefiles/Profiles.gmk Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/makefiles/Profiles.gmk Thu Aug 29 16:26:29 2013 -0700
@@ -65,10 +65,6 @@
$(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 @@
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)
--- a/jdk/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Thu Aug 29 16:26:29 2013 -0700
@@ -87,6 +87,7 @@
private int incomingInterruptFD;
static {
+ IOUtil.load();
initStructSizes();
String datamodel = java.security.AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("sun.arch.data.model")
--- a/jdk/src/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -246,9 +246,4 @@
}
return this;
}
-
-
- static {
- Util.load();
- }
}
--- a/jdk/src/share/back/SDE.c Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/back/SDE.c Thu Aug 29 16:26:29 2013 -0700
@@ -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.
--- a/jdk/src/share/classes/com/sun/tools/attach/VirtualMachine.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/com/sun/tools/attach/VirtualMachine.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
/*
- * 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 @@
* {@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 @@
* <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 @@
* 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 @@
* 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 @@
* <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 @@
* 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 @@
* 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 @@
* 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
--- a/jdk/src/share/classes/java/io/BufferedInputStream.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/io/BufferedInputStream.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
/*
- * 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 @@
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 @@
* @param in the underlying input stream.
*/
public BufferedInputStream(InputStream in) {
- this(in, defaultBufferSize);
+ this(in, DEFAULT_BUFFER_SIZE);
}
/**
@@ -215,8 +223,11 @@
} 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];
--- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java Thu Aug 29 16:26:29 2013 -0700
@@ -1307,7 +1307,7 @@
* 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 @@
* 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.
--- a/jdk/src/share/classes/java/lang/Class.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Class.java Thu Aug 29 16:26:29 2013 -0700
@@ -3338,8 +3338,16 @@
* @since 1.8
*/
public AnnotatedType getAnnotatedSuperclass() {
- return TypeAnnotationParser.buildAnnotatedSuperclass(getRawTypeAnnotations(), getConstantPool(), this);
-}
+ 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
--- a/jdk/src/share/classes/java/lang/Math.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/lang/Math.java Thu Aug 29 16:26:29 2013 -0700
@@ -698,11 +698,8 @@
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 @@
* @see Random#nextDouble()
*/
public static double random() {
- Random rnd = randomNumberGenerator;
- if (rnd == null) rnd = initRNG();
- return rnd.nextDouble();
+ return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
/**
--- a/jdk/src/share/classes/java/lang/ProcessBuilder.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/lang/ProcessBuilder.java Thu Aug 29 16:26:29 2013 -0700
@@ -29,7 +29,6 @@
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 @@
// 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
--- a/jdk/src/share/classes/java/lang/StrictMath.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/lang/StrictMath.java Thu Aug 29 16:26:29 2013 -0700
@@ -678,11 +678,8 @@
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 @@
* @see Random#nextDouble()
*/
public static double random() {
- Random rnd = randomNumberGenerator;
- if (rnd == null) rnd = initRNG();
- return rnd.nextDouble();
+ return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
/**
--- a/jdk/src/share/classes/java/math/BigDecimal.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/math/BigDecimal.java Thu Aug 29 16:26:29 2013 -0700
@@ -2659,28 +2659,32 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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));
--- a/jdk/src/share/classes/java/math/BigInteger.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/math/BigInteger.java Thu Aug 29 16:26:29 2013 -0700
@@ -2109,7 +2109,7 @@
// 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)
--- a/jdk/src/share/classes/java/rmi/server/RMISocketFactory.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/rmi/server/RMISocketFactory.java Thu Aug 29 16:26:29 2013 -0700
@@ -50,13 +50,13 @@
* @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 @@
* }</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
--- a/jdk/src/share/classes/java/util/Collections.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/Collections.java Thu Aug 29 16:26:29 2013 -0700
@@ -27,7 +27,6 @@
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.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 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 @@
* 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 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 @@
}
@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 @@
") > 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 @@
@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 @@
@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();}
}
}
--- a/jdk/src/share/classes/java/util/ComparableTimSort.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/ComparableTimSort.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,4 +1,5 @@
/*
+ * 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 @@
*/
int stackLen = (len < 120 ? 5 :
len < 1542 ? 10 :
- len < 119151 ? 19 : 40);
+ len < 119151 ? 24 : 40);
runBase = new int[stackLen];
runLen = new int[stackLen];
}
--- a/jdk/src/share/classes/java/util/Comparator.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/Comparator.java Thu Aug 29 16:26:29 2013 -0700
@@ -199,7 +199,7 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* @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 @@
* @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 @@
* @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));
--- a/jdk/src/share/classes/java/util/Random.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/Random.java Thu Aug 29 16:26:29 2013 -0700
@@ -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 @@
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
@@ -222,6 +233,82 @@
}
/**
+ * 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
* contract of {@code nextInt} is that one {@code int} value is
@@ -247,23 +334,23 @@
* 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 @@
* 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 n) {
- if (n <= 0)
- throw new IllegalArgumentException("n must be positive");
+ public int nextInt(int bound) {
+ if (bound <= 0)
+ throw new IllegalArgumentException(BadBound);
- 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 @@
* @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 @@
}
}
+ // stream methods, coded in a way intended to better isolate for
+ // maintenance purposes the small differences across forms.
+
/**
- * 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 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()}.
*
- * @return an infinite stream of {@code integer} 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
+ (this, 0L, streamSize, Integer.MAX_VALUE, 0),
+ false);
+ }
+
+ /**
+ * 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 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 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 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)}.
*
- * @return an infinite stream of {@code long} 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 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 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()}.
+ *
+ * @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 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 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)}.
*
- * @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 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 producing the given {@code streamSize} number 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()}}.
+ *
+ * @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 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)}.
+ *
+ * @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
+ (this, 0L, Long.MAX_VALUE, 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()}.
- *
- * @return an infinite stream of {@code double} values
- * @since 1.8
+ * 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.
*/
- public DoubleStream gaussians() {
- return DoubleStream.generate(this::nextGaussian);
+ 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);
+ }
+ }
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/SplittableRandom.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,1002 @@
+/*
+ * 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);
+ }
+ }
+ }
+
+}
--- a/jdk/src/share/classes/java/util/TimSort.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/TimSort.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,4 +1,5 @@
/*
+ * 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 @@
*/
int stackLen = (len < 120 ? 5 :
len < 1542 ? 10 :
- len < 119151 ? 19 : 40);
+ len < 119151 ? 24 : 40);
runBase = new int[stackLen];
runLen = new int[stackLen];
}
--- a/jdk/src/share/classes/java/util/TreeMap.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/TreeMap.java Thu Aug 29 16:26:29 2013 -0700
@@ -973,6 +973,27 @@
}
@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);
int expectedModCount = modCount;
--- a/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Thu Aug 29 16:26:29 2013 -0700
@@ -37,11 +37,16 @@
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 @@
* <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 @@
* 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.
+ * 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.
+ * 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 @@
* 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 @@
* 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 @@
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";
+
+ /**
+ * 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 = 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;
}
/**
- * Returns a pseudorandom, uniformly distributed value between the
- * given least value (inclusive) and bound (exclusive).
+ * 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 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
+ * @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(int least, int bound) {
- if (least >= bound)
- throw new IllegalArgumentException();
- return nextInt(bound - least) + least;
+ 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);
+ 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, uniformly distributed value
- * between 0 (inclusive) and the specified value (exclusive).
+ * Returns a pseudorandom {@code int} value between the specified
+ * origin (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 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 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);
+ public int nextInt(int origin, int bound) {
+ if (origin >= bound)
+ throw new IllegalArgumentException(BadRange);
+ return internalNextInt(origin, bound);
}
- @Override
- public IntStream ints() {
- return IntStream.generate(() -> current().nextInt());
+ /**
+ * Returns a pseudorandom {@code long} value.
+ *
+ * @return a pseudorandom {@code long} value
+ */
+ public long nextLong() {
+ return mix64(nextSeed());
}
- @Override
- public LongStream longs() {
- return LongStream.generate(() -> current().nextLong());
- }
-
- @Override
- public DoubleStream doubles() {
- return DoubleStream.generate(() -> current().nextDouble());
- }
-
- @Override
- public DoubleStream gaussians() {
- return DoubleStream.generate(() -> current().nextGaussian());
+ /**
+ * 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 least, long bound) {
- if (least >= bound)
- throw new IllegalArgumentException();
- return nextLong(bound - least) + least;
+ 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, 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 @@
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 @@
*/
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();
--- a/jdk/src/share/classes/java/util/concurrent/locks/StampedLock.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/concurrent/locks/StampedLock.java Thu Aug 29 16:26:29 2013 -0700
@@ -226,7 +226,11 @@
* 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 @@
/** 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 @@
* @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,17 +1019,8 @@
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;
- U.unpark(w);
- }
- if ((r = q.cowait) == null)
- break;
- U.compareAndSwapObject(q, WCOWAIT, r, r.cowait);
- }
- }
+ if (q != null && (w = q.thread) != null)
+ U.unpark(w);
}
}
@@ -1038,22 +1036,22 @@
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 @@
}
}
- 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,33 +1083,45 @@
--k <= 0)
break;
}
- if (spins < MAX_HEAD_SPINS)
- spins <<= 1;
}
- if ((ps = p.status) == 0)
- U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
- else if (ps == CANCELLED) {
- if ((pp = p.prev) != null) {
- node.prev = pp;
- pp.next = node;
+ 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);
}
}
- else {
- long time; // 0 argument to park means no timeout
- if (deadline == 0L)
- time = 0L;
- else if ((time = deadline - System.nanoTime()) <= 0L)
- return cancelWaiter(node, node, false);
- Thread wt = Thread.currentThread();
- U.putObject(wt, PARKBLOCKER, this); // emulate LockSupport.park
- node.thread = wt;
- if (node.prev == p && p.status == WAITING && // recheck
- (p != whead || (state & ABITS) != 0L))
- U.park(false, time);
- node.thread = null;
- U.putObject(wt, PARKBLOCKER, null);
- if (interruptible && Thread.interrupted())
- return cancelWaiter(node, node, true);
+ 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) {
+ node.prev = pp;
+ pp.next = node;
+ }
+ }
+ else {
+ long time; // 0 argument to park means no timeout
+ if (deadline == 0L)
+ time = 0L;
+ else if ((time = deadline - System.nanoTime()) <= 0L)
+ return cancelWaiter(node, node, false);
+ Thread wt = Thread.currentThread();
+ U.putObject(wt, PARKBLOCKER, this);
+ node.thread = wt;
+ 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())
+ return cancelWaiter(node, node, true);
+ }
}
}
}
@@ -1122,138 +1136,159 @@
* @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;
- 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);
+ 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))
+ return ns;
+ else if (m >= WBIT) {
+ if (spins > 0) {
+ if (LockSupport.nextSecondarySeed() >= 0)
+ --spins;
+ }
+ else {
+ if (spins == 0) {
+ WNode nh = whead, np = wtail;
+ if ((nh == h && np == p) || (h = nh) != (p = np))
+ break;
}
- if ((r = group.cowait) == null)
- break;
- U.compareAndSwapObject(group, WCOWAIT, r, r.cowait);
+ spins = SPINS;
}
}
- return ns;
}
- if (m >= WBIT)
- break;
+ }
+ if (p == null) { // initialize queue
+ WNode hd = new WNode(WMODE, null);
+ if (U.compareAndSwapObject(this, WHEAD, null, hd))
+ wtail = hd;
}
- 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;
+ else if (node == null)
+ node = new WNode(RMODE, p);
+ else if (h == p || p.mode != RMODE) {
+ if (node.prev != p)
+ node.prev = p;
+ else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
+ p.next = node;
+ break;
+ }
}
- else if (spins < 0)
- spins = (p == whead) ? SPINS : 0;
- else if (node == null)
- node = new WNode(WMODE, p);
- else 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(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;
- U.park(false, time);
+ 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) {
- whead = node;
- node.prev = null;
- while ((r = node.cowait) != null) {
- if (U.compareAndSwapObject(node, WCOWAIT,
- r, r.cowait) &&
- (w = r.thread) != null) {
- r.thread = null;
- U.unpark(w); // release co-waiter
- }
- }
- return ns;
+ 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 ((c = node.cowait) != null) {
+ if (U.compareAndSwapObject(node, WCOWAIT,
+ 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)
- U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
- else if (ps == CANCELLED) {
- if ((pp = p.prev) != null) {
- node.prev = pp;
- pp.next = node;
+ 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);
}
}
- else {
- long time;
- if (deadline == 0L)
- time = 0L;
- else if ((time = deadline - System.nanoTime()) <= 0L)
- return cancelWaiter(node, node, false);
- Thread wt = Thread.currentThread();
- U.putObject(wt, PARKBLOCKER, this);
- node.thread = wt;
- if (node.prev == p && p.status == WAITING &&
- (p != whead || (state & ABITS) != WBIT))
- U.park(false, time);
- node.thread = null;
- U.putObject(wt, PARKBLOCKER, null);
- if (interruptible && Thread.interrupted())
- return cancelWaiter(node, node, true);
+ 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) {
+ node.prev = pp;
+ pp.next = node;
+ }
+ }
+ else {
+ long time;
+ if (deadline == 0L)
+ time = 0L;
+ else if ((time = deadline - System.nanoTime()) <= 0L)
+ return cancelWaiter(node, node, false);
+ Thread wt = Thread.currentThread();
+ U.putObject(wt, PARKBLOCKER, this);
+ node.thread = wt;
+ 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);
+ if (interruptible && Thread.interrupted())
+ return cancelWaiter(node, node, true);
+ }
}
}
}
@@ -1278,22 +1313,19 @@
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
--- a/jdk/src/share/classes/java/util/jar/JarVerifier.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/jar/JarVerifier.java Thu Aug 29 16:26:29 2013 -0700
@@ -32,6 +32,7 @@
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 @@
return;
}
- if (uname.equals(JarFile.MANIFEST_NAME)) {
+ if (uname.equals(JarFile.MANIFEST_NAME) ||
+ uname.equals(JarIndex.INDEX_NAME)) {
return;
}
--- a/jdk/src/share/classes/java/util/logging/Logger.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java Thu Aug 29 16:26:29 2013 -0700
@@ -457,13 +457,15 @@
* 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 @@
// 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 @@
resourceBundleName + " != " + name);
}
+ if (name == null) {
+ return;
+ }
+
setCallersClassLoaderRef(callersClass);
if (findResourceBundle(name, true) == null) {
// We've failed to find an expected ResourceBundle.
--- a/jdk/src/share/classes/java/util/regex/Pattern.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/regex/Pattern.java Thu Aug 29 16:26:29 2013 -0700
@@ -219,7 +219,7 @@
*
* <tr><th> </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 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 block (<a href="#ubc">block</a>)</td></tr>
@@ -4456,16 +4456,16 @@
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 @@
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 @@
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++)
--- a/jdk/src/share/classes/java/util/stream/Collectors.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/Collectors.java Thu Aug 29 16:26:29 2013 -0700
@@ -137,6 +137,11 @@
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 @@
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 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 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),
- op.apply(left.forFalse, right.forFalse));
- };
- Supplier<Map<Boolean, A>> supplier = () -> new Partition<>(downstream.supplier().get(),
- downstream.supplier().get());
+ BinaryOperator<Partition<A>> merger = (left, right) ->
+ new Partition<>(op.apply(left.forTrue, right.forTrue),
+ op.apply(left.forFalse, right.forFalse));
+ 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);
}
}
--- a/jdk/src/share/classes/java/util/stream/DistinctOps.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/DistinctOps.java Thu Aug 29 16:26:29 2013 -0700
@@ -101,7 +101,7 @@
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 @@
}
};
} else {
- return new Sink.ChainedReference<T>(sink) {
+ return new Sink.ChainedReference<T, T>(sink) {
Set<T> seen;
@Override
--- a/jdk/src/share/classes/java/util/stream/DoublePipeline.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/DoublePipeline.java Thu Aug 29 16:26:29 2013 -0700
@@ -191,7 +191,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
--- a/jdk/src/share/classes/java/util/stream/IntPipeline.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/IntPipeline.java Thu Aug 29 16:26:29 2013 -0700
@@ -189,9 +189,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
--- a/jdk/src/share/classes/java/util/stream/LongPipeline.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/LongPipeline.java Thu Aug 29 16:26:29 2013 -0700
@@ -186,7 +186,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
--- a/jdk/src/share/classes/java/util/stream/ReferencePipeline.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/ReferencePipeline.java Thu Aug 29 16:26:29 2013 -0700
@@ -163,17 +163,16 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
@Override
+ @SuppressWarnings("unchecked")
public final <R, A> R collect(Collector<? super P_OUT, A, ? extends R> collector) {
A container;
if (isParallel()
--- a/jdk/src/share/classes/java/util/stream/Sink.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/Sink.java Thu Aug 29 16:26:29 2013 -0700
@@ -241,11 +241,10 @@
* 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 @@
* 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 @@
* 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 @@
* 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);
}
--- a/jdk/src/share/classes/java/util/stream/SliceOps.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/SliceOps.java Thu Aug 29 16:26:29 2013 -0700
@@ -96,6 +96,11 @@
}
}
+ @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.
@@ -107,12 +112,12 @@
* is to be imposed
*/
public static <T> Stream<T> makeRef(AbstractPipeline<?, T, ?> upstream,
- long skip, long limit) {
+ long skip, long limit) {
if (skip < 0)
throw new IllegalArgumentException("Skip must be non-negative: " + skip);
- return new ReferencePipeline.StatefulOp<T,T>(upstream, StreamShape.REFERENCE,
- flags(limit)) {
+ return new ReferencePipeline.StatefulOp<T, T>(upstream, StreamShape.REFERENCE,
+ flags(limit)) {
Spliterator<T> unorderedSkipLimitSpliterator(Spliterator<T> s,
long skip, long limit, long sizeIfKnown) {
if (skip <= sizeIfKnown) {
@@ -146,7 +151,7 @@
// 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 @@
@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 @@
@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 @@
@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 @@
@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 @@
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;
--- a/jdk/src/share/classes/java/util/stream/SortedOps.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/stream/SortedOps.java Thu Aug 29 16:26:29 2013 -0700
@@ -129,7 +129,7 @@
}
@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 @@
/**
* {@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 @@
/**
* {@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 @@
/**
* {@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 @@
/**
* {@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 @@
/**
* {@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 @@
/**
* {@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 @@
/**
* {@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 @@
/**
* {@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);
}
--- a/jdk/src/share/classes/java/util/zip/ZipOutputStream.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/java/util/zip/ZipOutputStream.java Thu Aug 29 16:26:29 2013 -0700
@@ -663,6 +663,9 @@
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 @@
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);
+ }
}
}
--- a/jdk/src/share/classes/javax/net/ssl/SNIHostName.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/javax/net/ssl/SNIHostName.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
/*
- * 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 @@
* 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
--- a/jdk/src/share/classes/javax/net/ssl/X509KeyManager.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/javax/net/ssl/X509KeyManager.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
/*
- * 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 @@
* <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>
--- a/jdk/src/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java Thu Aug 29 16:26:29 2013 -0700
@@ -197,8 +197,7 @@
* {@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 @@
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;
+ String myFullName = getName();
+ String otherFullName = ((KerberosPrincipal) other).getName();
+ return myFullName.equals(otherFullName);
}
/**
--- a/jdk/src/share/classes/sun/misc/Compare.java Thu Aug 29 09:42:03 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 1996, 1997, 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.
- */
-
-/**
- * Compare: an interface to enable users to define the result of
- * a comparison of two objects.
- *
- * @author Sunita Mani
- */
-
-package sun.misc;
-
-public interface Compare {
-
- /**
- * 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);
-
-}
--- a/jdk/src/share/classes/sun/misc/Sort.java Thu Aug 29 09:42:03 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 1996, 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.
- */
-
-/**
- * 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.
- */
- 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 */
- }
- 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);
- }
-}
--- a/jdk/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -193,9 +193,4 @@
if (!selch.isOpen() && !selch.isRegistered())
((SelChImpl)selch).kill();
}
-
- static {
- Util.load();
- }
-
}
--- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -1138,7 +1138,7 @@
throws IOException;
static {
- Util.load();
+ IOUtil.load();
initIDs();
}
--- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -1162,7 +1162,7 @@
private static native long initIDs();
static {
- Util.load();
+ IOUtil.load();
allocationGranularity = initIDs();
}
--- a/jdk/src/share/classes/sun/nio/ch/IOUtil.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/IOUtil.java Thu Aug 29 16:26:29 2013 -0700
@@ -347,9 +347,23 @@
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();
}
--- a/jdk/src/share/classes/sun/nio/ch/Net.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/Net.java Thu Aug 29 16:26:29 2013 -0700
@@ -582,7 +582,7 @@
private static native void initIDs();
static {
- Util.load();
+ IOUtil.load();
initIDs();
}
--- a/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -416,7 +416,7 @@
private static native void initIDs();
static {
- Util.load();
+ IOUtil.load();
initIDs();
nd = new SocketDispatcher();
}
--- a/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -1024,7 +1024,7 @@
throws IOException;
static {
- Util.load();
+ IOUtil.load();
nd = new SocketDispatcher();
}
--- a/jdk/src/share/classes/sun/nio/ch/Util.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/Util.java Thu Aug 29 16:26:29 2013 -0700
@@ -401,30 +401,4 @@
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();
- }
- }
-
}
--- a/jdk/src/share/classes/sun/tools/jconsole/ConnectDialog.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/ConnectDialog.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
/*
- * 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 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),
--- a/jdk/src/share/classes/sun/tools/jconsole/JConsole.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/JConsole.java Thu Aug 29 16:26:29 2013 -0700
@@ -858,6 +858,10 @@
try {
updateInterval = Integer.parseInt(arg.substring(10)) *
1000;
+ if (updateInterval <= 0) {
+ usage();
+ return;
+ }
} catch (NumberFormatException ex) {
usage();
return;
--- a/jdk/src/share/classes/sun/tools/jconsole/Messages.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/Messages.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
/*
- * 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 @@
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 @@
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;
--- a/jdk/src/share/classes/sun/tools/jconsole/Plotter.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/Plotter.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
/*
- * 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 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();
--- a/jdk/src/share/classes/sun/tools/jconsole/ThreadTab.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/ThreadTab.java Thu Aug 29 16:26:29 2013 -0700
@@ -595,6 +595,8 @@
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,
--- a/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/VMPanel.java Thu Aug 29 16:26:29 2013 -0700
@@ -153,9 +153,11 @@
// in order to reserve space for the connect toggle.
public void setUI(TabbedPaneUI ui) {
Insets insets = (Insets) UIManager.getLookAndFeelDefaults().get("TabbedPane.tabAreaInsets");
- insets = (Insets) insets.clone();
- insets.right += connectedIcon24.getIconWidth() + 8;
- UIManager.put("TabbedPane.tabAreaInsets", insets);
+ if (insets != null) {
+ insets = (Insets) insets.clone();
+ insets.right += connectedIcon24.getIconWidth() + 8;
+ UIManager.put("TabbedPane.tabAreaInsets", insets);
+ }
super.setUI(ui);
}
--- a/jdk/src/share/classes/sun/tools/jconsole/resources/messages.properties Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages.properties Thu Aug 29 16:26:29 2013 -0700
@@ -104,7 +104,6 @@
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 @@
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:
--- a/jdk/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties Thu Aug 29 16:26:29 2013 -0700
@@ -104,7 +104,6 @@
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)
--- a/jdk/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties Thu Aug 29 16:26:29 2013 -0700
@@ -104,7 +104,6 @@
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)
--- a/jdk/src/share/lib/security/java.security-linux Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/lib/security/java.security-linux Thu Aug 29 16:26:29 2013 -0700
@@ -181,6 +181,7 @@
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 @@
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.,\
--- a/jdk/src/share/lib/security/java.security-macosx Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/lib/security/java.security-macosx Thu Aug 29 16:26:29 2013 -0700
@@ -182,6 +182,7 @@
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 @@
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.,\
--- a/jdk/src/share/lib/security/java.security-solaris Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/lib/security/java.security-solaris Thu Aug 29 16:26:29 2013 -0700
@@ -183,6 +183,7 @@
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 @@
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.,\
--- a/jdk/src/share/lib/security/java.security-windows Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/lib/security/java.security-windows Thu Aug 29 16:26:29 2013 -0700
@@ -182,6 +182,7 @@
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 @@
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.,\
--- a/jdk/src/share/native/common/check_code.c Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/share/native/common/check_code.c Thu Aug 29 16:26:29 2013 -0700
@@ -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
--- a/jdk/src/solaris/classes/sun/nio/ch/DatagramDispatcher.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/DatagramDispatcher.java Thu Aug 29 16:26:29 2013 -0700
@@ -36,7 +36,7 @@
class DatagramDispatcher extends NativeDispatcher
{
static {
- Util.load();
+ IOUtil.load();
}
int read(FileDescriptor fd, long address, int len) throws IOException {
--- a/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java Thu Aug 29 16:26:29 2013 -0700
@@ -316,4 +316,8 @@
private native int poll0(long pollAddress, int numfds, long timeout,
int wfd);
private static native void interrupt(int fd);
+
+ static {
+ IOUtil.load();
+ }
}
--- a/jdk/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -196,9 +196,4 @@
}
return this;
}
-
- static {
- Util.load();
- }
-
}
--- a/jdk/src/solaris/classes/sun/nio/ch/EPoll.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/EPoll.java Thu Aug 29 16:26:29 2013 -0700
@@ -113,6 +113,6 @@
throws IOException;
static {
- Util.load();
+ IOUtil.load();
}
}
--- a/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java Thu Aug 29 16:26:29 2013 -0700
@@ -318,6 +318,7 @@
}
static {
+ IOUtil.load();
init();
}
--- a/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/EPollPort.java Thu Aug 29 16:26:29 2013 -0700
@@ -318,6 +318,6 @@
private static native void close0(int fd);
static {
- Util.load();
+ IOUtil.load();
}
}
--- a/jdk/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -196,8 +196,4 @@
}
return this;
}
-
- static {
- Util.load();
- }
}
--- a/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -31,7 +31,7 @@
{
static {
- Util.load();
+ IOUtil.load();
init();
}
--- a/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java Thu Aug 29 16:26:29 2013 -0700
@@ -235,6 +235,6 @@
private static native int peerPort0(int fd);
static {
- Util.load();
+ IOUtil.load();
}
}
--- a/jdk/src/solaris/classes/sun/nio/ch/KQueue.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/KQueue.java Thu Aug 29 16:26:29 2013 -0700
@@ -115,6 +115,6 @@
throws IOException;
static {
- Util.load();
+ IOUtil.load();
}
}
--- a/jdk/src/solaris/classes/sun/nio/ch/KQueuePort.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/KQueuePort.java Thu Aug 29 16:26:29 2013 -0700
@@ -326,6 +326,6 @@
private static native void close0(int fd);
static {
- Util.load();
+ IOUtil.load();
}
}
--- a/jdk/src/solaris/classes/sun/nio/ch/NativeThread.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/NativeThread.java Thu Aug 29 16:26:29 2013 -0700
@@ -54,7 +54,7 @@
private static native void init();
static {
- Util.load();
+ IOUtil.load();
init();
}
--- a/jdk/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java Thu Aug 29 16:26:29 2013 -0700
@@ -126,4 +126,7 @@
private static native void interrupt(int fd);
+ static {
+ IOUtil.load();
+ }
}
--- a/jdk/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -37,7 +37,7 @@
{
// 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 @@
throw new IndexOutOfBoundsException();
return write(Util.subsequence(srcs, offset, length));
}
-
- static {
- Util.load();
- nd = new FileDispatcherImpl();
- }
-
}
--- a/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java Thu Aug 29 16:26:29 2013 -0700
@@ -260,6 +260,6 @@
static {
- Util.load();
+ IOUtil.load();
}
}
--- a/jdk/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -37,7 +37,7 @@
{
// 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 @@
}
}
}
-
- static {
- Util.load();
- nd = new FileDispatcherImpl();
- }
-
}
--- a/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -345,7 +345,7 @@
throws IOException;
static {
- Util.load();
+ IOUtil.load();
initIDs();
}
}
--- a/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -748,6 +748,6 @@
private static native void checkConnect(int fdVal) throws IOException;
static {
- Util.load();
+ IOUtil.load();
}
}
--- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -1106,7 +1106,7 @@
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() {
--- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -995,7 +995,7 @@
}
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() {
--- a/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -426,7 +426,7 @@
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() {
--- a/jdk/src/windows/classes/sun/nio/ch/DatagramDispatcher.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/DatagramDispatcher.java Thu Aug 29 16:26:29 2013 -0700
@@ -36,7 +36,7 @@
class DatagramDispatcher extends NativeDispatcher
{
static {
- Util.load();
+ IOUtil.load();
}
int read(FileDescriptor fd, long address, int len) throws IOException {
--- a/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -32,7 +32,7 @@
class FileDispatcherImpl extends FileDispatcher
{
static {
- Util.load();
+ IOUtil.load();
}
/**
--- a/jdk/src/windows/classes/sun/nio/ch/FileKey.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/FileKey.java Thu Aug 29 16:26:29 2013 -0700
@@ -73,6 +73,7 @@
private static native void initIDs();
static {
+ IOUtil.load();
initIDs();
}
}
--- a/jdk/src/windows/classes/sun/nio/ch/Iocp.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/Iocp.java Thu Aug 29 16:26:29 2013 -0700
@@ -443,7 +443,7 @@
private static native String getErrorMessage(int error);
static {
- Util.load();
+ IOUtil.load();
initIDs();
// thread agnostic I/O on Vista/2008 or newer
--- a/jdk/src/windows/classes/sun/nio/ch/PipeImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/PipeImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -56,7 +56,6 @@
private static final Random rnd;
static {
- Util.load();
byte[] someBytes = new byte[8];
boolean resultOK = IOUtil.randomBytes(someBytes);
if (resultOK) {
--- a/jdk/src/windows/classes/sun/nio/ch/SocketDispatcher.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/SocketDispatcher.java Thu Aug 29 16:26:29 2013 -0700
@@ -36,7 +36,7 @@
{
static {
- Util.load();
+ IOUtil.load();
}
int read(FileDescriptor fd, long address, int len) throws IOException {
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -750,6 +750,6 @@
private static native void close0(long handle);
static {
- Util.load();
+ IOUtil.load();
}
}
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -363,7 +363,7 @@
private static native void closesocket0(long socket) throws IOException;
static {
- Util.load();
+ IOUtil.load();
initIDs();
}
}
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -919,7 +919,7 @@
private static native void closesocket0(long socket) throws IOException;
static {
- Util.load();
+ IOUtil.load();
initIDs();
}
}
--- a/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Thu Aug 29 16:26:29 2013 -0700
@@ -611,6 +611,6 @@
}
static {
- Util.load();
+ IOUtil.load();
}
}
--- a/jdk/test/ProblemList.txt Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/ProblemList.txt Thu Aug 29 16:26:29 2013 -0700
@@ -208,7 +208,7 @@
# jdk_io
# 7160013
-java/io/File/MaxPathLength.java windows-all
+#java/io/File/MaxPathLength.java windows-all
############################################################################
@@ -336,12 +336,6 @@
# 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
--- a/jdk/test/TEST.ROOT Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/TEST.ROOT Thu Aug 29 16:26:29 2013 -0700
@@ -9,3 +9,6 @@
# 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]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/TEST.groups Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,214 @@
+# 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/BufferedInputStream/LargeCopyWithMark.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,117 @@
+/*
+ * 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 {}
+}
--- a/jdk/test/java/io/File/MaxPathLength.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/io/File/MaxPathLength.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
/*
- * 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 @@
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());
--- a/jdk/test/java/io/pathNames/General.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/io/pathNames/General.java Thu Aug 29 16:26:29 2013 -0700
@@ -28,6 +28,7 @@
import java.io.*;
import java.util.*;
+import java.nio.file.*;
public class General {
@@ -57,7 +58,7 @@
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 @@
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 @@
}
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 @@
}
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 @@
/* 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)
--- a/jdk/test/java/lang/SecurityManager/CheckPackageAccess.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/lang/SecurityManager/CheckPackageAccess.java Thu Aug 29 16:26:29 2013 -0700
@@ -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 @@
"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.",
--- a/jdk/test/java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java Thu Aug 29 16:26:29 2013 -0700
@@ -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 @@
}
}
- 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 @@
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());
+ }
}
}
}
--- a/jdk/test/java/lang/annotation/TypeAnnotationReflection.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java Thu Aug 29 16:26:29 2013 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8004698 8007073
+ * @bug 8004698 8007073 8022343
* @summary Unit test for type annotations
*/
@@ -58,7 +58,7 @@
}
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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedSuperclass.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,56 @@
+/*
+ * 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 8022343
+ * @summary make sure Class.getAnnotatedSuperclass() returns null when specified to do so
+ */
+
+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");
+ }
+ }
+
+ if (failed != 0)
+ throw new RuntimeException("Test failed, check log for details");
+ }
+
+ interface If {}
+}
--- a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java Thu Aug 29 16:26:29 2013 -0700
@@ -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.*;
--- a/jdk/test/java/math/BigDecimal/IntegralDivisionTests.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/math/BigDecimal/IntegralDivisionTests.java Thu Aug 29 16:26:29 2013 -0700
@@ -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 @@
{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) {
--- a/jdk/test/java/nio/file/WatchService/SensitivityModifier.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/nio/file/WatchService/SensitivityModifier.java Thu Aug 29 16:26:29 2013 -0700
@@ -54,60 +54,66 @@
@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);
- int nFiles = 50 + rand.nextInt(50);
- Path[] dirs = new Path[nDirs];
- Path[] files = new Path[nFiles];
- for (int i=0; i<nDirs; i++) {
- dirs[i] = Files.createDirectory(top.resolve("dir" + i));
- }
- for (int i=0; i<nFiles; i++) {
- Path dir = dirs[rand.nextInt(nDirs)];
- files[i] = Files.createFile(dir.resolve("file" + i));
- }
+ // create directories and files
+ int nDirs = 5 + rand.nextInt(20);
+ int nFiles = 50 + rand.nextInt(50);
+ Path[] dirs = new Path[nDirs];
+ Path[] files = new Path[nFiles];
+ for (int i=0; i<nDirs; i++) {
+ dirs[i] = Files.createDirectory(top.resolve("dir" + i));
+ }
+ for (int i=0; i<nFiles; i++) {
+ Path dir = dirs[rand.nextInt(nDirs)];
+ files[i] = Files.createFile(dir.resolve("file" + i));
+ }
- // register the directories (random sensitivity)
- register(dirs, watcher);
+ // register the directories (random sensitivity)
+ register(dirs, watcher);
- // sleep a bit here to ensure that modification to the first file
- // can be detected by polling implementations (ie: last modified time
- // may not change otherwise).
- try { Thread.sleep(1000); } catch (InterruptedException e) { }
+ // sleep a bit here to ensure that modification to the first file
+ // can be detected by polling implementations (ie: last modified time
+ // may not change otherwise).
+ try { Thread.sleep(1000); } catch (InterruptedException e) { }
- // modify files and check that events are received
- for (int i=0; i<10; i++) {
- Path file = files[rand.nextInt(nFiles)];
- System.out.println("Modify: " + file);
- try (OutputStream out = Files.newOutputStream(file)) {
- out.write(new byte[100]);
+ // modify files and check that events are received
+ for (int i=0; i<10; i++) {
+ Path file = files[rand.nextInt(nFiles)];
+ System.out.println("Modify: " + file);
+ try (OutputStream out = Files.newOutputStream(file)) {
+ out.write(new byte[100]);
+ }
+
+ System.out.println("Waiting for event(s)...");
+ boolean eventReceived = false;
+ WatchKey key = watcher.take();
+ 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())) {
+ eventReceived = true;
+ break;
+ }
+ }
+ key.reset();
+ key = watcher.poll(1, TimeUnit.SECONDS);
+ } 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);
}
- System.out.println("Waiting for event...");
- WatchKey key = watcher.take();
- WatchEvent<?> event = key.pollEvents().iterator().next();
- 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();
- key.reset();
- key = watcher.poll(1, TimeUnit.SECONDS);
- } while (key != null);
-
- // re-register the directories to force changing their sensitivity
- // level
- register(dirs, watcher);
}
-
- // done
- watcher.close();
}
public static void main(String[] args) throws Exception {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Arrays/TimSortStackSize.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,116 @@
+/*
+ * 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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Collections/Wrappers.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,146 @@
+/*
+ * 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());
+ }
+ }
+}
+
--- a/jdk/test/java/util/Comparator/BasicTest.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/util/Comparator/BasicTest.java Thu Aug 29 16:26:29 2013 -0700
@@ -90,7 +90,7 @@
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 @@
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 @@
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 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 @@
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 @@
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 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 @@
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 @@
} 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) {}
}
--- a/jdk/test/java/util/Map/EntryComparators.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/util/Map/EntryComparators.java Thu Aug 29 16:26:29 2013 -0700
@@ -115,8 +115,8 @@
// 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],
--- a/jdk/test/java/util/Random/RandomStreamTest.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/util/Random/RandomStreamTest.java Thu Aug 29 16:26:29 2013 -0700
@@ -82,13 +82,6 @@
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();
@@ -132,20 +125,6 @@
}
@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();
testRandomResultSupplierConcurrently(() -> tlr.ints().limit(SIZE).boxed().collect(toList()));
@@ -163,12 +142,6 @@
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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Random/RandomTest.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,430 @@
+/*
+ * 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);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/SplittableRandom/SplittableRandomTest.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,560 @@
+/*
+ * 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);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,559 @@
+/*
+ * 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);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/locks/StampedLock/ReadersUnlockAfterWriteUnlock.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,88 @@
+/*
+ * 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;
+ }
+
+}
--- a/jdk/test/java/util/function/BinaryOperator/BasicTest.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/util/function/BinaryOperator/BasicTest.java Thu Aug 29 16:26:29 2013 -0700
@@ -67,26 +67,26 @@
};
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]);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/getLogger/TestLogger.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,98 @@
+/*
+ * 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));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/getLogger/testlogger/MyResource.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,52 @@
+/*
+ * 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 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;
+
+/**
+ * A dummy resource bundle for testing purposes.
+ * @author danielfuchs
+ */
+public class MyResource extends ResourceBundle {
+ Map<String, Object> bundle = new HashMap<>();
+
+ @Override
+ protected Object handleGetObject(String key) {
+ bundle.put(key,"Localized: " + key);
+ return bundle.get(key);
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ final Hashtable<String, Object> h = new Hashtable<>(bundle);
+ return h.keys();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/regex/PatternTest.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,147 @@
+/*
+ * 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();
+ }
+}
--- a/jdk/test/java/util/regex/RegExTest.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/util/regex/RegExTest.java Thu Aug 29 16:26:29 2013 -0700
@@ -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 @@
linebreakTest();
branchTest();
groupCurlyNotFoundSuppTest();
+ groupCurlyBackoffTest();
patternAsPredicate();
if (failure) {
throw new
@@ -3999,6 +4000,15 @@
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();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/SplittableRandomTest.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,367 @@
+/*
+ * 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();
+ }
+}
--- a/jdk/test/java/util/zip/TestExtraTime.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/java/util/zip/TestExtraTime.java Thu Aug 29 16:26:29 2013 -0700
@@ -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.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 @@
FileTime ctime = FileTime.from(time - 300000, TimeUnit.MILLISECONDS);
TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
- test(mtime, null, null, null);
- // ms-dos 1980 epoch problem
- test(FileTime.from(10, TimeUnit.MILLISECONDS), null, null, null);
- // non-default tz
- test(mtime, null, null, tz);
+ 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, extra);
+ // non-default 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 @@
}
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 @@
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 @@
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 @@
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!");
+ }
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/KPEquals.java Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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);
+ }
+}
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
/*
- * 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 @@
/*
* Signal Client, we're ready for his connect.
*/
- serverReady = true;
+ if (createdPorts == serverPorts.length) {
+ serverReady = true;
+ }
int read = 0;
int nConnections = 0;
/*
@@ -310,7 +314,6 @@
* Fork off the other side, then do your work.
*/
SessionCacheSizeTests() throws Exception {
-
/*
* create the SSLServerSocket and SSLSocket factories
*/
@@ -323,46 +326,87 @@
int serverConns = MAX_ACTIVE_CONNECTIONS / (serverPorts.length);
int remainingConns = MAX_ACTIVE_CONNECTIONS % (serverPorts.length);
- if (separateServerThread) {
- for (int i = 0; i < serverPorts.length; i++) {
-
- // distribute remaining connections among the available ports
- if (i < remainingConns)
- startServer(serverPorts[i], (serverConns + 1), true);
- else
- startServer(serverPorts[i], serverConns, true);
+ Exception startException = null;
+ try {
+ if (separateServerThread) {
+ for (int i = 0; i < serverPorts.length; i++) {
+ // distribute remaining connections among the
+ // available ports
+ if (i < remainingConns)
+ startServer(serverPorts[i], (serverConns + 1), true);
+ else
+ startServer(serverPorts[i], serverConns, true);
+ }
+ startClient(false);
+ } else {
+ startClient(true);
+ for (int i = 0; i < serverPorts.length; i++) {
+ if (i < remainingConns)
+ startServer(serverPorts[i], (serverConns + 1), false);
+ else
+ startServer(serverPorts[i], serverConns, false);
+ }
}
- startClient(false);
- } else {
- startClient(true);
- for (int i = 0; i < serverPorts.length; i++) {
- if (i < remainingConns)
- startServer(serverPorts[i], (serverConns + 1), false);
- else
- startServer(serverPorts[i], serverConns, false);
- }
+ } catch (Exception e) {
+ startException = e;
}
/*
* Wait for other side to close down.
*/
if (separateServerThread) {
- serverThread.join();
+ if (serverThread != null) {
+ serverThread.join();
+ }
} else {
- clientThread.join();
+ 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.
+ */
+ 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,
@@ -387,7 +431,13 @@
};
serverThread.start();
} else {
- doServerSide(port, nConns);
+ try {
+ doServerSide(port, nConns);
+ } catch (Exception e) {
+ serverException = e;
+ } finally {
+ serverReady = true;
+ }
}
}
@@ -409,7 +459,11 @@
};
clientThread.start();
} else {
- doClientSide();
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ clientException = e;
+ }
}
}
}
--- a/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java Thu Aug 29 16:26:29 2013 -0700
@@ -1,5 +1,5 @@
/*
- * 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.*;
@@ -263,7 +263,7 @@
for (int i = 0; i < nConnections; i++) {
sslSockets[i].close();
}
- System.out.println("----------------------------------------"
+ System.out.println("----------------------------------------"
+ "-----------------------");
System.out.println("Session timeout test passed");
}
@@ -348,45 +348,88 @@
int serverConns = MAX_ACTIVE_CONNECTIONS / (serverPorts.length);
int remainingConns = MAX_ACTIVE_CONNECTIONS % (serverPorts.length);
- if (separateServerThread) {
- for (int i = 0; i < serverPorts.length; i++) {
- // distribute remaining connections among the available ports
- if (i < remainingConns)
- startServer(serverPorts[i], (serverConns + 1), true);
- else
- startServer(serverPorts[i], serverConns, true);
+ Exception startException = null;
+ try {
+ if (separateServerThread) {
+ for (int i = 0; i < serverPorts.length; i++) {
+ // distribute remaining connections among the
+ // vailable ports
+ if (i < remainingConns)
+ startServer(serverPorts[i], (serverConns + 1), true);
+ else
+ startServer(serverPorts[i], serverConns, true);
+ }
+ startClient(false);
+ } else {
+ startClient(true);
+ for (int i = 0; i < serverPorts.length; i++) {
+ if (i < remainingConns)
+ startServer(serverPorts[i], (serverConns + 1), false);
+ else
+ startServer(serverPorts[i], serverConns, false);
+ }
}
- startClient(false);
- } else {
- startClient(true);
- for (int i = 0; i < serverPorts.length; i++) {
- if (i < remainingConns)
- startServer(serverPorts[i], (serverConns + 1), false);
- else
- startServer(serverPorts[i], serverConns, false);
- }
+ } catch (Exception e) {
+ startException = e;
}
/*
* Wait for other side to close down.
*/
if (separateServerThread) {
- serverThread.join();
+ if (serverThread != null) {
+ serverThread.join();
+ }
} else {
- clientThread.join();
+ 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 @@
};
serverThread.start();
} else {
- doServerSide(port, nConns);
+ try {
+ doServerSide(port, nConns);
+ } catch (Exception e) {
+ serverException = e;
+ } finally {
+ serverReady = 0;
+ }
}
}
@@ -433,7 +482,11 @@
};
clientThread.start();
} else {
- doClientSide();
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ clientException = e;
+ }
}
}
}
--- a/jdk/test/sun/security/ssl/templates/SSLSocketTemplate.java Thu Aug 29 09:42:03 2013 -0700
+++ b/jdk/test/sun/security/ssl/templates/SSLSocketTemplate.java Thu Aug 29 16:26:29 2013 -0700
@@ -243,7 +243,7 @@
* output it.
*/
if (exception != null) {
- if (exception != startException) {
+ if (exception != startException && startException != null) {
exception.addSuppressed(startException);
}
throw exception;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/jvindex.sh Thu Aug 29 16:26:29 2013 -0700
@@ -0,0 +1,76 @@
+#
+# 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
+
+