diff --git a/.hgtags b/.hgtags index df88b26f840fd28694db5f8677718ba3a1552fbf..c20c5cde8f0d7f5ad37b6be30d2864534357eb7c 100644 --- a/.hgtags +++ b/.hgtags @@ -227,3 +227,4 @@ c4908732fef5235f1b98cafe0ce507771ef7892c jdk8-b98 e0f6039c0290b7381042a6fec3100a69a5a67e37 jdk8-b103 f1d8d15bfcb5ada858a942f8a31f6598f23214d1 jdk8-b104 1fe211ae3d2b8cc2dfc4f58d9a6eb96418679672 jdk8-b105 +c817276bd870dfe1dcc3a3dbbc092436b6907f75 jdk8-b106 diff --git a/make/com/sun/security/auth/FILES_java.gmk b/make/com/sun/security/auth/FILES_java.gmk index 3e96e9d58b397ce595bd14aeca595046a5a90e0c..fa4f7d4b8d0ba0af17485ea0fc9699346a354ec5 100644 --- a/make/com/sun/security/auth/FILES_java.gmk +++ b/make/com/sun/security/auth/FILES_java.gmk @@ -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 @@ FILES_java = \ com/sun/security/auth/UserPrincipal.java \ com/sun/security/auth/LdapPrincipal.java \ com/sun/security/auth/PolicyFile.java \ - com/sun/security/auth/SubjectCodeSource.java \ - com/sun/security/auth/PolicyParser.java \ com/sun/security/auth/PrincipalComparator.java \ com/sun/security/auth/callback/TextCallbackHandler.java \ com/sun/security/auth/callback/DialogCallbackHandler.java diff --git a/makefiles/Profiles.gmk b/makefiles/Profiles.gmk index 47fadcc9df9deb2368902c9b2583b720133ecf15..9e79b2b27ac5b476840f74eec11315469663d2ed 100644 --- a/makefiles/Profiles.gmk +++ b/makefiles/Profiles.gmk @@ -65,10 +65,6 @@ PROFILE_2_JARS := \ $(if $(PROFILE_2_JRE_JAR_FILES), $(addprefix $(IMAGES_OUTPUTDIR)/lib/, $(PROFILE_2_JRE_JAR_FILES))) \ $(PROFILE_1_JARS) -ifneq ($(ENABLE_JFR), true) - PROFILE_3_JRE_JAR_FILES := $(filter-out jfr.jar, $(PROFILE_3_JRE_JAR_FILES)) -endif - PROFILE_3_JARS := \ $(addprefix $(IMAGES_OUTPUTDIR)/lib/, $(PROFILE_3_JRE_JAR_FILES)) \ $(PROFILE_2_JARS) @@ -77,6 +73,10 @@ ifdef OPENJDK FULL_JRE_JAR_FILES := $(filter-out alt-rt.jar, $(FULL_JRE_JAR_FILES)) endif +ifneq ($(ENABLE_JFR), true) + FULL_JRE_JAR_FILES := $(filter-out jfr.jar, $(FULL_JRE_JAR_FILES)) +endif + FULL_JRE_JARS := \ $(addprefix $(IMAGES_OUTPUTDIR)/lib/, $(FULL_JRE_JAR_FILES)) \ $(PROFILE_3_JARS) diff --git a/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java b/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java index b1f71acc4a3db417c03be3e0d131793992634ca9..5c82006000ccf549ffa5371025fbbc4f9407558b 100644 --- a/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java +++ b/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java @@ -87,6 +87,7 @@ class KQueueArrayWrapper { private int incomingInterruptFD; static { + IOUtil.load(); initStructSizes(); String datamodel = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("sun.arch.data.model") diff --git a/src/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java b/src/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java index 847c89bdccefe29c19c4def1c1791e0dfdc8c20c..f2340e62ca4c2d2d093516aaa000f1e0ddbd0499 100644 --- a/src/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java +++ b/src/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java @@ -246,9 +246,4 @@ class KQueueSelectorImpl } return this; } - - - static { - Util.load(); - } } diff --git a/src/share/back/SDE.c b/src/share/back/SDE.c index 34a43b07bff6320792ac594ddf6954400dc7c11d..cf7baa471491cee045353a0b13a17ebb798a8939 100644 --- a/src/share/back/SDE.c +++ b/src/share/back/SDE.c @@ -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. diff --git a/src/share/classes/com/sun/tools/attach/VirtualMachine.java b/src/share/classes/com/sun/tools/attach/VirtualMachine.java index aad0be2cfc9ec46bbe83b11422aa677a127d7a6c..29464d88da686e878e89e2adab586bcb03499bb9 100644 --- a/src/share/classes/com/sun/tools/attach/VirtualMachine.java +++ b/src/share/classes/com/sun/tools/attach/VirtualMachine.java @@ -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 @@ import java.io.IOException; * {@link java.lang.instrument} for a detailed description on how these agents * are loaded and started). The {@link #loadAgentLibrary loadAgentLibrary} and * {@link #loadAgentPath loadAgentPath} methods are used to load agents that - * are deployed in a dynamic library and make use of the JVM Tools * Interface.

* @@ -298,25 +298,29 @@ public abstract class VirtualMachine { *

A JVM * TI client is called an agent. 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 Agent_OnAttach function + * or, for a statically linked agent named 'L', the Agent_OnAttach_L function * as specified in the * JVM Tools - * Interface specification. Note that the Agent_OnAttach + * Interface specification. Note that the Agent_OnAttach[_L] * function is invoked even if the agent library was loaded prior to invoking * this method. * *

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 foo might be expanded to - * libfoo.so, and located using the search path specified by the - * LD_LIBRARY_PATH environment variable.

+ * name. For example, on UNIX systems, the name L might be expanded to + * libL.so, and located using the search path specified by the + * LD_LIBRARY_PATH environment variable. If the agent named 'L' is + * statically linked into the VM then the VM must export a function named + * Agent_OnAttach_L.

* - *

If the Agent_OnAttach function in the agent library returns + *

If the Agent_OnAttach[_L] function in the agent library returns * an error then an {@link com.sun.tools.attach.AgentInitializationException} is - * thrown. The return value from the Agent_OnAttach can then be + * thrown. The return value from the Agent_OnAttach[_L] can then be * obtained by invoking the {@link * com.sun.tools.attach.AgentInitializationException#returnValue() returnValue} * method on the exception.

@@ -325,15 +329,16 @@ public abstract class VirtualMachine { * The name of the agent library. * * @param options - * The options to provide to the Agent_OnAttach + * The options to provide to the Agent_OnAttach[_L] * function (can be null). * * @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 Agent_OnAttach function returns an error + * If the Agent_OnAttach[_L] function returns an error. * * @throws IOException * If an I/O error occurs @@ -359,11 +364,12 @@ public abstract class VirtualMachine { * The name of the agent library. * * @throws AgentLoadException - * If the agent library does not exist, or cannot be loaded for - * another reason. + * If the agent library does not exist, the agent library is not + * statically linked with the VM, or the agent library cannot be + * loaded for another reason. * * @throws AgentInitializationException - * If the Agent_OnAttach function returns an error + * If the Agent_OnAttach[_L] function returns an error. * * @throws IOException * If an I/O error occurs @@ -383,12 +389,23 @@ public abstract class VirtualMachine { *

A JVM * TI client is called an agent. 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 Agent_OnAttach 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 /a/b/libL.so 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 Agent_OnAttach + * function or, for a statically linked agent named 'L', the + * Agent_OnAttach_L function as specified in the * JVM Tools - * Interface specification. Note that the Agent_OnAttach + * Interface specification. + * Note that the Agent_OnAttach[_L] * function is invoked even if the agent library was loaded prior to invoking * this method. * @@ -396,9 +413,9 @@ public abstract class VirtualMachine { * agent library. Unlike {@link #loadAgentLibrary loadAgentLibrary}, the library name * is not expanded in the target virtual machine.

* - *

If the Agent_OnAttach function in the agent library returns + *

If the Agent_OnAttach[_L] function in the agent library returns * an error then an {@link com.sun.tools.attach.AgentInitializationException} is - * thrown. The return value from the Agent_OnAttach can then be + * thrown. The return value from the Agent_OnAttach[_L] can then be * obtained by invoking the {@link * com.sun.tools.attach.AgentInitializationException#returnValue() returnValue} * method on the exception.

@@ -407,15 +424,16 @@ public abstract class VirtualMachine { * The full path of the agent library. * * @param options - * The options to provide to the Agent_OnAttach + * The options to provide to the Agent_OnAttach[_L] * function (can be null). * * @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 Agent_OnAttach function returns an error + * If the Agent_OnAttach[_L] function returns an error. * * @throws IOException * If an I/O error occurs @@ -441,11 +459,12 @@ public abstract class VirtualMachine { * The full path to the agent library. * * @throws AgentLoadException - * If the agent library does not exist, or cannot be loaded for - * another reason. + * If the agent library does not exist, the agent library is not + * statically linked with the VM, or the agent library cannot be + * loaded for another reason. * * @throws AgentInitializationException - * If the Agent_OnAttach function returns an error + * If the Agent_OnAttach[_L] function returns an error. * * @throws IOException * If an I/O error occurs diff --git a/src/share/classes/java/io/BufferedInputStream.java b/src/share/classes/java/io/BufferedInputStream.java index a161a9881098d096456791055c002cc07417b239..fede2feeb7fd302143d0b71e19bfad788da0e9fc 100644 --- a/src/share/classes/java/io/BufferedInputStream.java +++ b/src/share/classes/java/io/BufferedInputStream.java @@ -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 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; public class BufferedInputStream extends FilterInputStream { - private static int defaultBufferSize = 8192; + private static int DEFAULT_BUFFER_SIZE = 8192; + + /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8; /** * The internal buffer array where the data is stored. When necessary, @@ -172,7 +180,7 @@ class BufferedInputStream extends FilterInputStream { * @param in the underlying input stream. */ public BufferedInputStream(InputStream in) { - this(in, defaultBufferSize); + this(in, DEFAULT_BUFFER_SIZE); } /** @@ -215,8 +223,11 @@ class BufferedInputStream extends FilterInputStream { } else if (buffer.length >= marklimit) { markpos = -1; /* buffer got too big, invalidate mark */ pos = 0; /* drop buffer contents */ + } else if (buffer.length >= MAX_BUFFER_SIZE) { + throw new OutOfMemoryError("Required array size too large"); } else { /* grow buffer */ - int nsz = pos * 2; + int nsz = (pos <= MAX_BUFFER_SIZE - pos) ? + pos * 2 : MAX_BUFFER_SIZE; if (nsz > marklimit) nsz = marklimit; byte nbuf[] = new byte[nsz]; diff --git a/src/share/classes/java/lang/AbstractStringBuilder.java b/src/share/classes/java/lang/AbstractStringBuilder.java index a5bde616f8a25d6e41b467b873b9e2b0fc64df34..3260da6ae998aa6142d0765fe6baf8a69f44dea1 100644 --- a/src/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/share/classes/java/lang/AbstractStringBuilder.java @@ -1307,7 +1307,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * specified substring, starting at the specified index. The integer * returned is the smallest value {@code k} for which: *
-     *     k >= Math.min(fromIndex, str.length()) &&
+     *     k >= Math.min(fromIndex, this.length()) &&
      *                   this.toString().startsWith(str, k)
      * 
* If no such value of k exists, then -1 is returned. @@ -1346,7 +1346,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { * specified substring. The integer returned is the largest value k * such that: *
-     *     k <= Math.min(fromIndex, str.length()) &&
+     *     k <= Math.min(fromIndex, this.length()) &&
      *                   this.toString().startsWith(str, k)
      * 
* If no such value of k exists, then -1 is returned. diff --git a/src/share/classes/java/lang/Class.java b/src/share/classes/java/lang/Class.java index 46fff084bec527014fcf773554ccefecd6ca1c33..7895c62b3cccb38348b67991bf76351a18453f4d 100644 --- a/src/share/classes/java/lang/Class.java +++ b/src/share/classes/java/lang/Class.java @@ -3354,8 +3354,16 @@ public final class Class implements java.io.Serializable, * @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 diff --git a/src/share/classes/java/lang/Math.java b/src/share/classes/java/lang/Math.java index 23bc934688d4a4990bc888a73a4adfd35bda619c..ae83e4265ad6f49a64f33ddf1b1db475d82b9f4c 100644 --- a/src/share/classes/java/lang/Math.java +++ b/src/share/classes/java/lang/Math.java @@ -698,11 +698,8 @@ public final class Math { return 0; } - private static Random randomNumberGenerator; - - private static synchronized Random initRNG() { - Random rnd = randomNumberGenerator; - return (rnd == null) ? (randomNumberGenerator = new Random()) : rnd; + private static final class RandomNumberGeneratorHolder { + static final Random randomNumberGenerator = new Random(); } /** @@ -729,9 +726,7 @@ public final class Math { * @see Random#nextDouble() */ public static double random() { - Random rnd = randomNumberGenerator; - if (rnd == null) rnd = initRNG(); - return rnd.nextDouble(); + return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble(); } /** diff --git a/src/share/classes/java/lang/ProcessBuilder.java b/src/share/classes/java/lang/ProcessBuilder.java index 0cb7febe533df4ef2dc5cc88cb473e741ddb948e..53fbc489a6834983a24f4cd6fd92bd6ae38d8f3c 100644 --- a/src/share/classes/java/lang/ProcessBuilder.java +++ b/src/share/classes/java/lang/ProcessBuilder.java @@ -29,7 +29,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.AccessControlException; import java.util.Arrays; import java.util.ArrayList; import java.util.List; @@ -1033,9 +1032,9 @@ public final class ProcessBuilder // Can not disclose the fail reason for read-protected files. try { security.checkRead(prog); - } catch (AccessControlException ace) { + } catch (SecurityException se) { exceptionInfo = ""; - cause = ace; + cause = se; } } // It's much easier for us to create a high-quality error diff --git a/src/share/classes/java/lang/StrictMath.java b/src/share/classes/java/lang/StrictMath.java index eb202d5320287fd9d98744171d57ca220ace5069..52336484e7509a460b48783ae9f6f44659e27f59 100644 --- a/src/share/classes/java/lang/StrictMath.java +++ b/src/share/classes/java/lang/StrictMath.java @@ -678,11 +678,8 @@ public final class StrictMath { return Math.round(a); } - private static Random randomNumberGenerator; - - private static synchronized Random initRNG() { - Random rnd = randomNumberGenerator; - return (rnd == null) ? (randomNumberGenerator = new Random()) : rnd; + private static final class RandomNumberGeneratorHolder { + static final Random randomNumberGenerator = new Random(); } /** @@ -709,9 +706,7 @@ public final class StrictMath { * @see Random#nextDouble() */ public static double random() { - Random rnd = randomNumberGenerator; - if (rnd == null) rnd = initRNG(); - return rnd.nextDouble(); + return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble(); } /** diff --git a/src/share/classes/java/math/BigDecimal.java b/src/share/classes/java/math/BigDecimal.java index 1a7ca8112262d34709df97bb5d5fc7a6f8931f58..0abfb7522b5b11edfcce8a9bf7345a963999216c 100644 --- a/src/share/classes/java/math/BigDecimal.java +++ b/src/share/classes/java/math/BigDecimal.java @@ -2659,28 +2659,32 @@ public class BigDecimal extends Number implements Comparable { if (ys == 0) return 1; - int sdiff = this.scale - val.scale; + long sdiff = (long)this.scale - val.scale; if (sdiff != 0) { // Avoid matching scales if the (adjusted) exponents differ - int xae = this.precision() - this.scale; // [-1] - int yae = val.precision() - val.scale; // [-1] + long xae = (long)this.precision() - this.scale; // [-1] + long yae = (long)val.precision() - val.scale; // [-1] if (xae < yae) return -1; if (xae > yae) return 1; BigInteger rb = null; if (sdiff < 0) { - if ( (xs == INFLATED || - (xs = longMultiplyPowerTen(xs, -sdiff)) == INFLATED) && + // The cases sdiff <= Integer.MIN_VALUE intentionally fall through. + if ( sdiff > Integer.MIN_VALUE && + (xs == INFLATED || + (xs = longMultiplyPowerTen(xs, (int)-sdiff)) == INFLATED) && ys == INFLATED) { - rb = bigMultiplyPowerTen(-sdiff); + rb = bigMultiplyPowerTen((int)-sdiff); return rb.compareMagnitude(val.intVal); } } else { // sdiff > 0 - if ( (ys == INFLATED || - (ys = longMultiplyPowerTen(ys, sdiff)) == INFLATED) && + // The cases sdiff > Integer.MAX_VALUE intentionally fall through. + if ( sdiff <= Integer.MAX_VALUE && + (ys == INFLATED || + (ys = longMultiplyPowerTen(ys, (int)sdiff)) == INFLATED) && xs == INFLATED) { - rb = val.bigMultiplyPowerTen(sdiff); + rb = val.bigMultiplyPowerTen((int)sdiff); return this.intVal.compareMagnitude(rb); } } @@ -4545,7 +4549,7 @@ public class BigDecimal extends Number implements Comparable { if(cmp > 0) { // satisfy constraint (b) yscale -= 1; // [that is, divisor *= 10] int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp); - if (checkScaleNonZero((long) mcp + yscale) > xscale) { + if (checkScaleNonZero((long) mcp + yscale - xscale) > 0) { // assert newScale >= xscale int raise = checkScaleNonZero((long) mcp + yscale - xscale); long scaledXs; @@ -4626,7 +4630,7 @@ public class BigDecimal extends Number implements Comparable { // return BigDecimal object whose scale will be set to 'scl'. int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp); BigDecimal quotient; - if (checkScaleNonZero((long) mcp + yscale) > xscale) { + if (checkScaleNonZero((long) mcp + yscale - xscale) > 0) { int raise = checkScaleNonZero((long) mcp + yscale - xscale); long scaledXs; if ((scaledXs = longMultiplyPowerTen(xs, raise)) == INFLATED) { @@ -4673,7 +4677,7 @@ public class BigDecimal extends Number implements Comparable { // return BigDecimal object whose scale will be set to 'scl'. BigDecimal quotient; int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp); - if (checkScaleNonZero((long) mcp + yscale) > xscale) { + if (checkScaleNonZero((long) mcp + yscale - xscale) > 0) { int raise = checkScaleNonZero((long) mcp + yscale - xscale); BigInteger rb = bigMultiplyPowerTen(xs,raise); quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale)); @@ -4714,7 +4718,7 @@ public class BigDecimal extends Number implements Comparable { // return BigDecimal object whose scale will be set to 'scl'. BigDecimal quotient; int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp); - if (checkScaleNonZero((long) mcp + yscale) > xscale) { + if (checkScaleNonZero((long) mcp + yscale - xscale) > 0) { int raise = checkScaleNonZero((long) mcp + yscale - xscale); BigInteger rb = bigMultiplyPowerTen(xs,raise); quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale)); @@ -4745,7 +4749,7 @@ public class BigDecimal extends Number implements Comparable { // 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)); diff --git a/src/share/classes/java/math/BigInteger.java b/src/share/classes/java/math/BigInteger.java index e8cedf8a564842e98306ae8b5d367a7e044e9178..6beaed71bb339f6036de101a37736f16941ab511 100644 --- a/src/share/classes/java/math/BigInteger.java +++ b/src/share/classes/java/math/BigInteger.java @@ -2109,7 +2109,7 @@ public class BigInteger extends Number implements Comparable { // 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) diff --git a/src/share/classes/java/rmi/server/RMISocketFactory.java b/src/share/classes/java/rmi/server/RMISocketFactory.java index e7b7581820b6661f62c17ad55f7d778fa1e1f45e..ec9ade2f54c875ad6b9ca7178e3b433bf0ed2cb6 100644 --- a/src/share/classes/java/rmi/server/RMISocketFactory.java +++ b/src/share/classes/java/rmi/server/RMISocketFactory.java @@ -50,13 +50,13 @@ import java.net.*; * @implNote *

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. * *

{@code
  *     class LoopbackSocketFactory extends RMISocketFactory {
  *         public ServerSocket createServerSocket(int port) throws IOException {
- *             return new ServerSocket(port, 5, InetAddress.getLoopbackAddress());
+ *             return new ServerSocket(port, 5, InetAddress.getByName("127.0.0.1"));
  *         }
  *
  *         public Socket createSocket(String host, int port) throws IOException {
@@ -72,8 +72,8 @@ import java.net.*;
  * }
* * 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 diff --git a/src/share/classes/java/util/Collections.java b/src/share/classes/java/util/Collections.java index 16263277f702deeddd66de0da349d92783e82b78..2404b4fc9adc880f134961173832e520f1acb371 100644 --- a/src/share/classes/java/util/Collections.java +++ b/src/share/classes/java/util/Collections.java @@ -27,7 +27,6 @@ package java.util; import java.io.Serializable; import java.io.ObjectOutputStream; import java.io.IOException; -import java.io.InvalidObjectException; import java.lang.reflect.Array; import java.util.function.BiConsumer; import java.util.function.BiFunction; @@ -35,6 +34,7 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.UnaryOperator; +import java.util.stream.IntStream; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -1148,7 +1148,16 @@ public class Collections { public Spliterator spliterator() { return (Spliterator)c.spliterator(); } - + @SuppressWarnings("unchecked") + @Override + public Stream stream() { + return (Stream)c.stream(); + } + @SuppressWarnings("unchecked") + @Override + public Stream parallelStream() { + return (Stream)c.parallelStream(); + } } /** @@ -2009,8 +2018,8 @@ public class Collections { * through the returned collection.

* * 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}: *

      *  Collection c = Collections.synchronizedCollection(myCollection);
      *     ...
@@ -2120,6 +2129,14 @@ public class Collections {
         public Spliterator spliterator() {
             return c.spliterator(); // Must be manually synched by user!
         }
+        @Override
+        public Stream stream() {
+            return c.stream(); // Must be manually synched by user!
+        }
+        @Override
+        public Stream parallelStream() {
+            return c.parallelStream(); // Must be manually synched by user!
+        }
         private void writeObject(ObjectOutputStream s) throws IOException {
             synchronized (mutex) {s.defaultWriteObject();}
         }
@@ -3172,6 +3189,10 @@ public class Collections {
         }
         @Override
         public Spliterator spliterator() {return c.spliterator();}
+        @Override
+        public Stream stream()           {return c.stream();}
+        @Override
+        public Stream parallelStream()   {return c.parallelStream();}
     }
 
     /**
@@ -5096,6 +5117,22 @@ public class Collections {
                                                    ") > toIndex(" + toIndex + ")");
             return new CopiesList<>(toIndex - fromIndex, element);
         }
+
+        // Override default methods in Collection
+        @Override
+        public Stream stream() {
+            return IntStream.range(0, n).mapToObj(i -> element);
+        }
+
+        @Override
+        public Stream parallelStream() {
+            return IntStream.range(0, n).parallel().mapToObj(i -> element);
+        }
+
+        @Override
+        public Spliterator spliterator() {
+            return stream().spliterator();
+        }
     }
 
     /**
@@ -5503,6 +5540,10 @@ public class Collections {
 
         @Override
         public Spliterator spliterator() {return s.spliterator();}
+        @Override
+        public Stream stream()           {return s.stream();}
+        @Override
+        public Stream parallelStream()   {return s.parallelStream();}
 
         private static final long serialVersionUID = 2454657854757543876L;
 
@@ -5568,10 +5609,14 @@ public class Collections {
         @Override
         public void forEach(Consumer action) {q.forEach(action);}
         @Override
-        public Spliterator spliterator() {return q.spliterator();}
-        @Override
         public boolean removeIf(Predicate filter) {
             return q.removeIf(filter);
         }
+        @Override
+        public Spliterator spliterator() {return q.spliterator();}
+        @Override
+        public Stream stream()           {return q.stream();}
+        @Override
+        public Stream parallelStream()   {return q.parallelStream();}
     }
 }
diff --git a/src/share/classes/java/util/ComparableTimSort.java b/src/share/classes/java/util/ComparableTimSort.java
index 76b5fd56a00f6c46963162291f39886a14b6ae15..e7c7ac020bd0a35e07d034f47050f5f26b0e4b76 100644
--- a/src/share/classes/java/util/ComparableTimSort.java
+++ b/src/share/classes/java/util/ComparableTimSort.java
@@ -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 @@ class ComparableTimSort {
          */
         int stackLen = (len <    120  ?  5 :
                         len <   1542  ? 10 :
-                        len < 119151  ? 19 : 40);
+                        len < 119151  ? 24 : 40);
         runBase = new int[stackLen];
         runLen = new int[stackLen];
     }
diff --git a/src/share/classes/java/util/Comparator.java b/src/share/classes/java/util/Comparator.java
index 55d5efb986678e4216d3c8088cb05cc71f1970f6..b19481df198725346d6489e63bf22ed02bd4e75e 100644
--- a/src/share/classes/java/util/Comparator.java
+++ b/src/share/classes/java/util/Comparator.java
@@ -199,7 +199,7 @@ public interface Comparator {
      * composed using following code,
      *
      * 
{@code
-     *     Comparator cmp = Comparator.comparing(String::length)
+     *     Comparator cmp = Comparator.comparingInt(String::length)
      *             .thenComparing(String.CASE_INSENSITIVE_ORDER);
      * }
* @@ -270,18 +270,18 @@ public interface Comparator { * 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 thenComparing(ToIntFunction keyExtractor) { - return thenComparing(comparing(keyExtractor)); + default Comparator thenComparingInt(ToIntFunction keyExtractor) { + return thenComparing(comparingInt(keyExtractor)); } /** @@ -289,18 +289,18 @@ public interface Comparator { * 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 thenComparing(ToLongFunction keyExtractor) { - return thenComparing(comparing(keyExtractor)); + default Comparator thenComparingLong(ToLongFunction keyExtractor) { + return thenComparing(comparingLong(keyExtractor)); } /** @@ -308,18 +308,18 @@ public interface Comparator { * 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 thenComparing(ToDoubleFunction keyExtractor) { - return thenComparing(comparing(keyExtractor)); + default Comparator thenComparingDouble(ToDoubleFunction keyExtractor) { + return thenComparing(comparingDouble(keyExtractor)); } /** @@ -484,7 +484,7 @@ public interface Comparator { * @throws NullPointerException if the argument is null * @since 1.8 */ - public static Comparator comparing(ToIntFunction keyExtractor) { + public static Comparator comparingInt(ToIntFunction keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator & Serializable) (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2)); @@ -505,7 +505,7 @@ public interface Comparator { * @throws NullPointerException if the argument is null * @since 1.8 */ - public static Comparator comparing(ToLongFunction keyExtractor) { + public static Comparator comparingLong(ToLongFunction keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator & Serializable) (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2)); @@ -526,7 +526,7 @@ public interface Comparator { * @throws NullPointerException if the argument is null * @since 1.8 */ - public static Comparator comparing(ToDoubleFunction keyExtractor) { + public static Comparator comparingDouble(ToDoubleFunction keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator & Serializable) (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2)); diff --git a/src/share/classes/java/util/Random.java b/src/share/classes/java/util/Random.java index ae2551c0f9bd9782be2f3230a1306feef928ee60..2c0e0135c729ad4e700739d4c6289da567c0a920 100644 --- a/src/share/classes/java/util/Random.java +++ b/src/share/classes/java/util/Random.java @@ -26,9 +26,13 @@ package java.util; import java.io.*; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; +import java.util.stream.StreamSupport; import sun.misc.Unsafe; @@ -85,6 +89,13 @@ class Random implements java.io.Serializable { private static final long addend = 0xBL; private static final long mask = (1L << 48) - 1; + private static final double DOUBLE_UNIT = 1.0 / (1L << 53); + + // IllegalArgumentException messages + static final String BadBound = "bound must be positive"; + static final String BadRange = "bound must be greater than origin"; + static final String BadSize = "size must be non-negative"; + /** * Creates a new random number generator. This constructor sets * the seed of the random number generator to a value very likely @@ -221,6 +232,82 @@ class Random implements java.io.Serializable { bytes[i++] = (byte)rnd; } + /** + * The form of nextLong used by LongStream Spliterators. If + * origin is greater than bound, acts as unbounded form of + * nextLong, else as bounded form. + * + * @param origin the least value, unless greater than bound + * @param bound the upper bound (exclusive), must not equal origin + * @return a pseudorandom value + */ + final long internalNextLong(long origin, long bound) { + long r = nextLong(); + if (origin < bound) { + long n = bound - origin, m = n - 1; + if ((n & m) == 0L) // power of two + r = (r & m) + origin; + else if (n > 0L) { // reject over-represented candidates + for (long u = r >>> 1; // ensure nonnegative + u + m - (r = u % n) < 0L; // rejection check + u = nextLong() >>> 1) // retry + ; + r += origin; + } + else { // range not representable as long + while (r < origin || r >= bound) + r = nextLong(); + } + } + return r; + } + + /** + * The form of nextInt used by IntStream Spliterators. + * For the unbounded case: uses nextInt(). + * For the bounded case with representable range: uses nextInt(int bound) + * For the bounded case with unrepresentable range: uses nextInt() + * + * @param origin the least value, unless greater than bound + * @param bound the upper bound (exclusive), must not equal origin + * @return a pseudorandom value + */ + final int internalNextInt(int origin, int bound) { + if (origin < bound) { + int n = bound - origin; + if (n > 0) { + return nextInt(n) + origin; + } + else { // range not representable as int + int r; + do { + r = nextInt(); + } while (r < origin || r >= bound); + return r; + } + } + else { + return nextInt(); + } + } + + /** + * The form of nextDouble used by DoubleStream Spliterators. + * + * @param origin the least value, unless greater than bound + * @param bound the upper bound (exclusive), must not equal origin + * @return a pseudorandom value + */ + final double internalNextDouble(double origin, double bound) { + double r = nextDouble(); + if (origin < bound) { + r = r * (bound - origin) + origin; + if (r >= bound) // correct for rounding + r = Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1); + } + return r; + } + /** * Returns the next pseudorandom, uniformly distributed {@code int} * value from this random number generator's sequence. The general @@ -247,23 +334,23 @@ class Random implements java.io.Serializable { * between 0 (inclusive) and the specified value (exclusive), drawn from * this random number generator's sequence. The general contract of * {@code nextInt} is that one {@code int} value in the specified range - * is pseudorandomly generated and returned. All {@code n} possible + * is pseudorandomly generated and returned. All {@code bound} possible * {@code int} values are produced with (approximately) equal - * probability. The method {@code nextInt(int n)} is implemented by + * probability. The method {@code nextInt(int bound)} is implemented by * class {@code Random} as if by: *
 {@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;
      * }}
* @@ -289,28 +376,28 @@ class Random implements java.io.Serializable { * greatly increases the length of the sequence of values returned by * successive calls to this method if n is a small power of two. * - * @param n the bound on the random number to be returned. Must be - * positive. + * @param bound the upper bound (exclusive). Must be positive. * @return the next pseudorandom, uniformly distributed {@code int} - * value between {@code 0} (inclusive) and {@code n} (exclusive) + * value between zero (inclusive) and {@code bound} (exclusive) * from this random number generator's sequence - * @throws IllegalArgumentException if n is not positive + * @throws IllegalArgumentException if bound is not positive * @since 1.2 */ + public int nextInt(int bound) { + if (bound <= 0) + throw new IllegalArgumentException(BadBound); - public int nextInt(int n) { - if (n <= 0) - throw new IllegalArgumentException("n must be positive"); - - if ((n & -n) == n) // i.e., n is a power of 2 - return (int)((n * (long)next(31)) >> 31); - - int bits, val; - do { - bits = next(31); - val = bits % n; - } while (bits - val + (n-1) < 0); - return val; + int r = next(31); + int m = bound - 1; + if ((bound & m) == 0) // i.e., bound is a power of 2 + r = (int)((bound * (long)r) >> 31); + else { + for (int u = r; + u - (r = u % bound) + m < 0; + u = next(31)) + ; + } + return r; } /** @@ -442,8 +529,7 @@ class Random implements java.io.Serializable { * @see Math#random */ public double nextDouble() { - return (((long)(next(26)) << 27) + next(27)) - / (double)(1L << 53); + return (((long)(next(26)) << 27) + next(27)) * DOUBLE_UNIT; } private double nextNextGaussian; @@ -513,57 +599,563 @@ class Random implements java.io.Serializable { } } + // stream methods, coded in a way intended to better isolate for + // maintenance purposes the small differences across forms. + /** - * Returns a stream 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. * - * @return an infinite stream of {@code integer} values + *

A pseudorandom {@code int} value is generated as if it's the result of + * calling the method {@link #nextInt()}. + * + * @param streamSize the number of values to generate + * @return a stream of pseudorandom {@code int} values + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + * @since 1.8 + */ + public IntStream ints(long streamSize) { + if (streamSize < 0L) + throw new IllegalArgumentException(BadSize); + return StreamSupport.intStream + (new RandomIntsSpliterator + (this, 0L, streamSize, Integer.MAX_VALUE, 0), + false); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code int} + * values. + * + *

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). + * + *

A pseudorandom {@code int} value is generated as if it's the result of + * calling the following method with the origin and bound: + *

 {@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;
+     *   }
+     * }}
+ * + * @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). + * + *

A pseudorandom {@code int} value is generated as if it's the result of + * calling the following method with the origin and bound: + *

 {@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;
+     *   }
+     * }}
+ * + * @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. + * + *

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. + * + *

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). + * + *

A pseudorandom {@code long} value is generated as if it's the result + * of calling the following method with the origin and bound: + *

 {@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;
+     * }}
+ * + * @param streamSize the number of values to generate + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * @return a stream of pseudorandom {@code long} values, + * each with the given origin (inclusive) and bound (exclusive) + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero, or {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * @since 1.8 + */ + public LongStream longs(long streamSize, long randomNumberOrigin, + long randomNumberBound) { + if (streamSize < 0L) + throw new IllegalArgumentException(BadSize); + if (randomNumberOrigin >= randomNumberBound) + throw new IllegalArgumentException(BadRange); + return StreamSupport.longStream + (new RandomLongsSpliterator + (this, 0L, streamSize, randomNumberOrigin, randomNumberBound), + false); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code + * long} values, each conforming to the given origin (inclusive) and bound + * (exclusive). + * + *

A pseudorandom {@code long} value is generated as if it's the result + * of calling the following method with the origin and bound: + *

 {@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;
+     * }}
+ * + * @implNote This method is implemented to be equivalent to {@code + * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. + * + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * @return a stream of pseudorandom {@code long} values, + * each with the given origin (inclusive) and bound (exclusive) + * @throws IllegalArgumentException if {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * @since 1.8 + */ + public LongStream longs(long randomNumberOrigin, long randomNumberBound) { + if (randomNumberOrigin >= randomNumberBound) + throw new IllegalArgumentException(BadRange); + return StreamSupport.longStream + (new RandomLongsSpliterator + (this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), + false); } /** - * Returns a stream of pseudorandom, uniformly distributed - * {@code double} values between {@code 0.0} and {@code 1.0} - * from this random number generator's sequence. Values are - * obtained as needed by calling {@link #nextDouble()}. + * Returns a stream producing the given {@code streamSize} number of + * pseudorandom {@code double} values, each between zero + * (inclusive) and one (exclusive). + * + *

A pseudorandom {@code double} value is generated as if it's the result + * of calling the method {@link #nextDouble()}}. * - * @return an infinite stream of {@code double} values + * @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). + * + *

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 of pseudorandom, Gaussian ("normally") - * distributed {@code double} values with mean {@code 0.0} - * and standard deviation {@code 1.0} from this random number - * generator's sequence. Values are obtained as needed by - * calling {@link #nextGaussian()}. + * Returns a stream producing the given {@code streamSize} number of + * pseudorandom {@code double} values, each conforming to the given origin + * (inclusive) and bound (exclusive). + * + *

A pseudorandom {@code double} value is generated as if it's the result + * of calling the following method with the origin and bound: + *

 {@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;
+     * }}
* - * @return an infinite stream of {@code double} values + * @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 gaussians() { - return DoubleStream.generate(this::nextGaussian); + 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). + * + *

A pseudorandom {@code double} value is generated as if it's the result + * of calling the following method with the origin and bound: + *

 {@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;
+     * }}
+ * + * @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); + } + + /** + * Spliterator for int streams. We multiplex the four int + * versions into one class by treating a bound less than origin as + * unbounded, and also by treating "infinite" as equivalent to + * Long.MAX_VALUE. For splits, it uses the standard divide-by-two + * approach. The long and double versions of this class are + * identical except for types. + */ + static final class RandomIntsSpliterator implements Spliterator.OfInt { + final Random rng; + long index; + final long fence; + final int origin; + final int bound; + RandomIntsSpliterator(Random rng, long index, long fence, + int origin, int bound) { + this.rng = rng; this.index = index; this.fence = fence; + this.origin = origin; this.bound = bound; + } + + public RandomIntsSpliterator trySplit() { + long i = index, m = (i + fence) >>> 1; + return (m <= i) ? null : + new RandomIntsSpliterator(rng, i, index = m, origin, bound); + } + + public long estimateSize() { + return fence - index; + } + + public int characteristics() { + return (Spliterator.SIZED | Spliterator.SUBSIZED | + Spliterator.NONNULL | Spliterator.IMMUTABLE); + } + + public boolean tryAdvance(IntConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(rng.internalNextInt(origin, bound)); + index = i + 1; + return true; + } + return false; + } + + public void forEachRemaining(IntConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + Random r = rng; + int o = origin, b = bound; + do { + consumer.accept(r.internalNextInt(o, b)); + } while (++i < f); + } + } + } + + /** + * Spliterator for long streams. + */ + static final class RandomLongsSpliterator implements Spliterator.OfLong { + final Random rng; + long index; + final long fence; + final long origin; + final long bound; + RandomLongsSpliterator(Random rng, long index, long fence, + long origin, long bound) { + this.rng = rng; this.index = index; this.fence = fence; + this.origin = origin; this.bound = bound; + } + + public RandomLongsSpliterator trySplit() { + long i = index, m = (i + fence) >>> 1; + return (m <= i) ? null : + new RandomLongsSpliterator(rng, i, index = m, origin, bound); + } + + public long estimateSize() { + return fence - index; + } + + public int characteristics() { + return (Spliterator.SIZED | Spliterator.SUBSIZED | + Spliterator.NONNULL | Spliterator.IMMUTABLE); + } + + public boolean tryAdvance(LongConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(rng.internalNextLong(origin, bound)); + index = i + 1; + return true; + } + return false; + } + + public void forEachRemaining(LongConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + Random r = rng; + long o = origin, b = bound; + do { + consumer.accept(r.internalNextLong(o, b)); + } while (++i < f); + } + } + + } + + /** + * Spliterator for double streams. + */ + static final class RandomDoublesSpliterator implements Spliterator.OfDouble { + final Random rng; + long index; + final long fence; + final double origin; + final double bound; + RandomDoublesSpliterator(Random rng, long index, long fence, + double origin, double bound) { + this.rng = rng; this.index = index; this.fence = fence; + this.origin = origin; this.bound = bound; + } + + public RandomDoublesSpliterator trySplit() { + long i = index, m = (i + fence) >>> 1; + return (m <= i) ? null : + new RandomDoublesSpliterator(rng, i, index = m, origin, bound); + } + + public long estimateSize() { + return fence - index; + } + + public int characteristics() { + return (Spliterator.SIZED | Spliterator.SUBSIZED | + Spliterator.NONNULL | Spliterator.IMMUTABLE); + } + + public boolean tryAdvance(DoubleConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(rng.internalNextDouble(origin, bound)); + index = i + 1; + return true; + } + return false; + } + + public void forEachRemaining(DoubleConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + Random r = rng; + double o = origin, b = bound; + do { + consumer.accept(r.internalNextDouble(o, b)); + } while (++i < f); + } + } } /** diff --git a/src/share/classes/java/util/SplittableRandom.java b/src/share/classes/java/util/SplittableRandom.java new file mode 100644 index 0000000000000000000000000000000000000000..5a990f4d2153c4170c152b265f1175b629af7ecc --- /dev/null +++ b/src/share/classes/java/util/SplittableRandom.java @@ -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: + * + *
    + * + *
  • Series of generated values pass the DieHarder suite testing + * independence and uniformity properties of random number generators. + * (Most recently validated with version + * 3.31.1.) 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 period + * (length of any series of generated values before it repeats) is at + * least 264.
  • + * + *
  • 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.
  • + * + *
  • Instances of SplittableRandom are not 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()}. + * + *
  • This class provides additional methods for generating random + * streams, that employ the above techniques when used in {@code + * stream.parallel()} mode.
  • + * + *
+ * + *

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 214, 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 (264) 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); + } + } + } + +} diff --git a/src/share/classes/java/util/TimSort.java b/src/share/classes/java/util/TimSort.java index 35493ff0bd6c9721cf8a7fb8891f69f6af17834e..9966f74df370c272615e9749a52e78cc49e1ead2 100644 --- a/src/share/classes/java/util/TimSort.java +++ b/src/share/classes/java/util/TimSort.java @@ -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 @@ class TimSort { */ int stackLen = (len < 120 ? 5 : len < 1542 ? 10 : - len < 119151 ? 19 : 40); + len < 119151 ? 24 : 40); runBase = new int[stackLen]; runLen = new int[stackLen]; } diff --git a/src/share/classes/java/util/TreeMap.java b/src/share/classes/java/util/TreeMap.java index 52d9df25a0b218e0e929927c5af951694a333796..9a4681d771a3345081118d166760b8d4ae9ca2dd 100644 --- a/src/share/classes/java/util/TreeMap.java +++ b/src/share/classes/java/util/TreeMap.java @@ -972,6 +972,27 @@ public class TreeMap return tailMap(fromKey, true); } + @Override + public boolean replace(K key, V oldValue, V newValue) { + Entry 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 p = getEntry(key); + if (p!=null) { + V oldValue = p.value; + p.value = value; + return oldValue; + } + return null; + } + @Override public void forEach(BiConsumer action) { Objects.requireNonNull(action); diff --git a/src/share/classes/java/util/concurrent/ThreadLocalRandom.java b/src/share/classes/java/util/concurrent/ThreadLocalRandom.java index 0532d3d4382b34c87de5e1b02e66a57871bfe2ea..297f88cd5a3e6932407848797cbcb26f32b7382d 100644 --- a/src/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/src/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -37,11 +37,16 @@ package java.util.concurrent; import java.io.ObjectStreamField; import java.util.Random; +import java.util.Spliterator; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; +import java.util.stream.StreamSupport; /** * A random number generator isolated to the current thread. Like the @@ -64,6 +69,10 @@ import java.util.stream.LongStream; *

This class also provides additional commonly used bounded random * generation methods. * + *

Instances of {@code ThreadLocalRandom} are not cryptographically + * secure. Consider instead using {@link java.security.SecureRandom} + * in security-sensitive applications. + * * @since 1.7 * @author Doug Lea */ @@ -85,28 +94,26 @@ public class ThreadLocalRandom extends Random { * application-level overhead and footprint of most concurrent * programs. * + * Even though this class subclasses java.util.Random, it uses the + * same basic algorithm as java.util.SplittableRandom. (See its + * internal documentation for explanations, which are not repeated + * here.) Because ThreadLocalRandoms are not splittable + * though, we use only a single 64bit gamma. + * * Because this class is in a different package than class Thread, * field access methods use Unsafe to bypass access control rules. - * The base functionality of Random methods is conveniently - * isolated in method next(bits), that just reads and writes the - * Thread field rather than its own field. However, to conform to - * the requirements of the Random superclass constructor, the - * common static ThreadLocalRandom maintains an "initialized" - * field for the sake of rejecting user calls to setSeed while - * still allowing a call from constructor. Note that - * serialization is completely unnecessary because there is only a - * static singleton. But we generate a serial form containing - * "rnd" and "initialized" fields to ensure compatibility across - * versions. - * - * Per-thread initialization is similar to that in the no-arg - * Random constructor, but we avoid correlation among not only - * initial seeds of those created in different threads, but also - * those created using class Random itself; while at the same time - * not changing any statistical properties. So we use the same - * underlying multiplicative sequence, but start the sequence far - * away from the base version, and then merge (xor) current time - * and per-thread probe bits to generate initial values. + * To conform to the requirements of the Random superclass + * constructor, the common static ThreadLocalRandom maintains an + * "initialized" field for the sake of rejecting user calls to + * setSeed while still allowing a call from constructor. Note + * that serialization is completely unnecessary because there is + * only a static singleton. But we generate a serial form + * containing "rnd" and "initialized" fields to ensure + * compatibility across versions. + * + * Implementations of non-core methods are mostly the same as in + * SplittableRandom, that were in part derived from a previous + * version of this class. * * The nextLocalGaussian ThreadLocal supports the very rarely used * nextGaussian method by providing a holder for the second of a @@ -115,24 +122,51 @@ public class ThreadLocalRandom extends Random { * but we provide identical statistical properties. */ - // same constants as Random, but must be redeclared because private - private static final long multiplier = 0x5DEECE66DL; - private static final long addend = 0xBL; - private static final long mask = (1L << 48) - 1; - private static final int PROBE_INCREMENT = 0x61c88647; - - /** Generates the basis for per-thread initial seed values */ - private static final AtomicLong seedGenerator = - new AtomicLong(1269533684904616924L); - /** Generates per-thread initialization/probe field */ private static final AtomicInteger probeGenerator = - new AtomicInteger(0xe80f8647); + new AtomicInteger(); + + /** + * The next seed for default constructors. + */ + private static final AtomicLong seeder = + new AtomicLong(mix64(System.currentTimeMillis()) ^ + mix64(System.nanoTime())); + + /** + * The seed increment + */ + private static final long GAMMA = 0x9e3779b97f4a7c15L; + + /** + * The increment for generating probe values + */ + private static final int PROBE_INCREMENT = 0x9e3779b9; + + /** + * The increment of seeder per new instance + */ + private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL; + + // Constants from SplittableRandom + private static final double DOUBLE_UNIT = 1.0 / (1L << 53); + private static final float FLOAT_UNIT = 1.0f / (1 << 24); /** Rarely-used holder for the second of a pair of Gaussians */ private static final ThreadLocal nextLocalGaussian = new ThreadLocal(); + private static long mix64(long z) { + z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL; + z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L; + return z ^ (z >>> 33); + } + + private static int mix32(long z) { + z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL; + return (int)(((z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L) >>> 32); + } + /** * Field used only during singleton initialization. * True when constructor completes. @@ -155,16 +189,11 @@ public class ThreadLocalRandom extends Random { * rely on (static) atomic generators to initialize the values. */ static final void localInit() { - int p = probeGenerator.getAndAdd(PROBE_INCREMENT); + int p = probeGenerator.addAndGet(PROBE_INCREMENT); int probe = (p == 0) ? 1 : p; // skip 0 - long current, next; - do { // same sequence as j.u.Random but different initial value - current = seedGenerator.get(); - next = current * 181783497276652981L; - } while (!seedGenerator.compareAndSet(current, next)); - long r = next ^ ((long)probe << 32) ^ System.nanoTime(); + long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT)); Thread t = Thread.currentThread(); - UNSAFE.putLong(t, SEED, r); + UNSAFE.putLong(t, SEED, seed); UNSAFE.putInt(t, PROBE, probe); } @@ -191,124 +220,264 @@ public class ThreadLocalRandom extends Random { throw new UnsupportedOperationException(); } - protected int next(int bits) { + final long nextSeed() { Thread t; long r; // read and update per-thread seed - UNSAFE.putLong - (t = Thread.currentThread(), SEED, - r = (UNSAFE.getLong(t, SEED) * multiplier + addend) & mask); - return (int) (r >>> (48-bits)); + UNSAFE.putLong(t = Thread.currentThread(), SEED, + r = UNSAFE.getLong(t, SEED) + GAMMA); + return r; } + // We must define this, but never use it. + protected int next(int bits) { + return (int)(mix64(nextSeed()) >>> (64 - bits)); + } + + // IllegalArgumentException messages + static final String BadBound = "bound must be positive"; + static final String BadRange = "bound must be greater than origin"; + static final String BadSize = "size must be non-negative"; + /** - * Returns a pseudorandom, uniformly distributed value between the - * given least value (inclusive) and bound (exclusive). + * The form of nextLong used by LongStream Spliterators. If + * origin is greater than bound, acts as unbounded form of + * nextLong, else as bounded form. * - * @param least the least value returned - * @param bound the upper bound (exclusive) - * @throws IllegalArgumentException if least greater than or equal - * to bound - * @return the next value - */ - public int nextInt(int least, int bound) { - if (least >= bound) - throw new IllegalArgumentException(); - return nextInt(bound - least) + least; - } - - /** - * Returns a pseudorandom, uniformly distributed value - * between 0 (inclusive) and the specified value (exclusive). - * - * @param n the bound on the random number to be returned. Must be - * positive. - * @return the next value - * @throws IllegalArgumentException if n is not positive - */ - public long nextLong(long n) { - if (n <= 0) - throw new IllegalArgumentException("n must be positive"); - // Divide n by two until small enough for nextInt. On each - // iteration (at most 31 of them but usually much less), - // randomly choose both whether to include high bit in result - // (offset) and whether to continue with the lower vs upper - // half (which makes a difference only if odd). - long offset = 0; - while (n >= Integer.MAX_VALUE) { - int bits = next(2); - long half = n >>> 1; - long nextn = ((bits & 2) == 0) ? half : n - half; - if ((bits & 1) == 0) - offset += n - nextn; - n = nextn; + * @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 offset + nextInt((int) n); + return r; } - @Override - public IntStream ints() { - return IntStream.generate(() -> current().nextInt()); + /** + * The form of nextInt used by IntStream Spliterators. + * Exactly the same as long version, except for types. + * + * @param origin the least value, unless greater than bound + * @param bound the upper bound (exclusive), must not equal origin + * @return a pseudorandom value + */ + final int internalNextInt(int origin, int bound) { + int r = mix32(nextSeed()); + if (origin < bound) { + int n = bound - origin, m = n - 1; + if ((n & m) == 0) + r = (r & m) + origin; + else if (n > 0) { + for (int u = r >>> 1; + u + m - (r = u % n) < 0; + u = mix32(nextSeed()) >>> 1) + ; + r += origin; + } + else { + while (r < origin || r >= bound) + r = mix32(nextSeed()); + } + } + return r; } - @Override - public LongStream longs() { - return LongStream.generate(() -> current().nextLong()); + /** + * 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; } - @Override - public DoubleStream doubles() { - return DoubleStream.generate(() -> current().nextDouble()); + /** + * Returns a pseudorandom {@code int} value. + * + * @return a pseudorandom {@code int} value + */ + public int nextInt() { + return mix32(nextSeed()); } - @Override - public DoubleStream gaussians() { - return DoubleStream.generate(() -> current().nextGaussian()); + /** + * Returns a pseudorandom {@code int} value between zero (inclusive) + * and the specified bound (exclusive). + * + * @param bound the upper bound (exclusive). Must be positive. + * @return a pseudorandom {@code int} value between zero + * (inclusive) and the bound (exclusive) + * @throws IllegalArgumentException if {@code bound} is not positive + */ + public int nextInt(int bound) { + if (bound <= 0) + throw new IllegalArgumentException(BadBound); + int r = mix32(nextSeed()); + int m = bound - 1; + if ((bound & m) == 0) // power of two + r &= m; + else { // reject over-represented candidates + for (int u = r >>> 1; + u + m - (r = u % bound) < 0; + u = mix32(nextSeed()) >>> 1) + ; + } + return r; } /** - * Returns a pseudorandom, uniformly distributed value between the - * given least value (inclusive) and bound (exclusive). + * Returns a pseudorandom {@code int} 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 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 least, long bound) { - if (least >= bound) - throw new IllegalArgumentException(); - return nextLong(bound - least) + least; + public int nextInt(int origin, int bound) { + if (origin >= bound) + throw new IllegalArgumentException(BadRange); + return internalNextInt(origin, bound); } /** - * Returns a pseudorandom, uniformly distributed {@code double} value - * between 0 (inclusive) and the specified value (exclusive). + * Returns a pseudorandom {@code long} value. * - * @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 + * @return a pseudorandom {@code long} value */ - public double nextDouble(double n) { - if (n <= 0) - throw new IllegalArgumentException("n must be positive"); - return nextDouble() * n; + public long nextLong() { + return mix64(nextSeed()); } /** - * Returns a pseudorandom, uniformly distributed value between the - * given least value (inclusive) and bound (exclusive). + * Returns a pseudorandom {@code long} value between zero (inclusive) + * and the specified bound (exclusive). * - * @param least the least value returned + * @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 {@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 the next value - * @throws IllegalArgumentException if least greater than or equal - * to bound + * @return a pseudorandom {@code long} value between the origin + * (inclusive) and the bound (exclusive) + * @throws IllegalArgumentException if {@code origin} is greater than + * or equal to {@code bound} + */ + public long nextLong(long origin, long bound) { + if (origin >= bound) + throw new IllegalArgumentException(BadRange); + return internalNextLong(origin, bound); + } + + /** + * Returns a pseudorandom {@code double} value between zero + * (inclusive) and one (exclusive). + * + * @return a pseudorandom {@code double} value between zero + * (inclusive) and one (exclusive) + */ + public 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 double nextDouble(double least, double bound) { - if (least >= bound) - throw new IllegalArgumentException(); - return nextDouble() * (bound - least) + least; + public boolean nextBoolean() { + return mix32(nextSeed()) < 0; + } + + /** + * Returns a pseudorandom {@code float} value between zero + * (inclusive) and one (exclusive). + * + * @return a pseudorandom {@code float} value between zero + * (inclusive) and one (exclusive) + */ + public float nextFloat() { + return (mix32(nextSeed()) >>> 8) * FLOAT_UNIT; } public double nextGaussian() { @@ -329,6 +498,445 @@ public class ThreadLocalRandom extends Random { return v1 * multiplier; } + // stream methods, coded in a way intended to better isolate for + // maintenance purposes the small differences across forms. + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandom {@code int} values. + * + * @param streamSize the number of values to generate + * @return a stream of pseudorandom {@code int} values + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + * @since 1.8 + */ + public IntStream ints(long streamSize) { + if (streamSize < 0L) + throw new IllegalArgumentException(BadSize); + return StreamSupport.intStream + (new RandomIntsSpliterator + (0L, streamSize, Integer.MAX_VALUE, 0), + false); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code int} + * values. + * + * @implNote This method is implemented to be equivalent to {@code + * ints(Long.MAX_VALUE)}. + * + * @return a stream of pseudorandom {@code int} values + * @since 1.8 + */ + public IntStream ints() { + return StreamSupport.intStream + (new RandomIntsSpliterator + (0L, Long.MAX_VALUE, Integer.MAX_VALUE, 0), + false); + } + + /** + * Returns a stream producing the given {@code streamSize} number + * of pseudorandom {@code int} values, each conforming to the given + * origin (inclusive) and bound (exclusive). + * + * @param streamSize the number of values to generate + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * @return a stream of pseudorandom {@code int} values, + * each with the given origin (inclusive) and bound (exclusive) + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero, or {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * @since 1.8 + */ + public IntStream ints(long streamSize, int randomNumberOrigin, + int randomNumberBound) { + if (streamSize < 0L) + throw new IllegalArgumentException(BadSize); + if (randomNumberOrigin >= randomNumberBound) + throw new IllegalArgumentException(BadRange); + return StreamSupport.intStream + (new RandomIntsSpliterator + (0L, streamSize, randomNumberOrigin, randomNumberBound), + false); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code + * int} values, each conforming to the given origin (inclusive) and bound + * (exclusive). + * + * @implNote This method is implemented to be equivalent to {@code + * ints(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. + * + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * @return a stream of pseudorandom {@code int} values, + * each with the given origin (inclusive) and bound (exclusive) + * @throws IllegalArgumentException if {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * @since 1.8 + */ + public IntStream ints(int randomNumberOrigin, int randomNumberBound) { + if (randomNumberOrigin >= randomNumberBound) + throw new IllegalArgumentException(BadRange); + return StreamSupport.intStream + (new RandomIntsSpliterator + (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), + false); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandom {@code long} values. + * + * @param streamSize the number of values to generate + * @return a stream of pseudorandom {@code long} values + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + * @since 1.8 + */ + public LongStream longs(long streamSize) { + if (streamSize < 0L) + throw new IllegalArgumentException(BadSize); + return StreamSupport.longStream + (new RandomLongsSpliterator + (0L, streamSize, Long.MAX_VALUE, 0L), + false); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code long} + * values. + * + * @implNote This method is implemented to be equivalent to {@code + * longs(Long.MAX_VALUE)}. + * + * @return a stream of pseudorandom {@code long} values + * @since 1.8 + */ + public LongStream longs() { + return StreamSupport.longStream + (new RandomLongsSpliterator + (0L, Long.MAX_VALUE, Long.MAX_VALUE, 0L), + false); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandom {@code long}, each conforming to the given origin + * (inclusive) and bound (exclusive). + * + * @param streamSize the number of values to generate + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * @return a stream of pseudorandom {@code long} values, + * each with the given origin (inclusive) and bound (exclusive) + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero, or {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * @since 1.8 + */ + public LongStream longs(long streamSize, long randomNumberOrigin, + long randomNumberBound) { + if (streamSize < 0L) + throw new IllegalArgumentException(BadSize); + if (randomNumberOrigin >= randomNumberBound) + throw new IllegalArgumentException(BadRange); + return StreamSupport.longStream + (new RandomLongsSpliterator + (0L, streamSize, randomNumberOrigin, randomNumberBound), + false); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code + * long} values, each conforming to the given origin (inclusive) and bound + * (exclusive). + * + * @implNote This method is implemented to be equivalent to {@code + * longs(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. + * + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * @return a stream of pseudorandom {@code long} values, + * each with the given origin (inclusive) and bound (exclusive) + * @throws IllegalArgumentException if {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * @since 1.8 + */ + public LongStream longs(long randomNumberOrigin, long randomNumberBound) { + if (randomNumberOrigin >= randomNumberBound) + throw new IllegalArgumentException(BadRange); + return StreamSupport.longStream + (new RandomLongsSpliterator + (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), + false); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandom {@code double} values, each between zero + * (inclusive) and one (exclusive). + * + * @param streamSize the number of values to generate + * @return a stream of {@code double} values + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + * @since 1.8 + */ + public DoubleStream doubles(long streamSize) { + if (streamSize < 0L) + throw new IllegalArgumentException(BadSize); + return StreamSupport.doubleStream + (new RandomDoublesSpliterator + (0L, streamSize, Double.MAX_VALUE, 0.0), + false); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code + * double} values, each between zero (inclusive) and one + * (exclusive). + * + * @implNote This method is implemented to be equivalent to {@code + * doubles(Long.MAX_VALUE)}. + * + * @return a stream of pseudorandom {@code double} values + * @since 1.8 + */ + public DoubleStream doubles() { + return StreamSupport.doubleStream + (new RandomDoublesSpliterator + (0L, Long.MAX_VALUE, Double.MAX_VALUE, 0.0), + false); + } + + /** + * Returns a stream producing the given {@code streamSize} number of + * pseudorandom {@code double} values, each conforming to the given origin + * (inclusive) and bound (exclusive). + * + * @param streamSize the number of values to generate + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * @return a stream of pseudorandom {@code double} values, + * each with the given origin (inclusive) and bound (exclusive) + * @throws IllegalArgumentException if {@code streamSize} is + * less than zero + * @throws IllegalArgumentException if {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * @since 1.8 + */ + public DoubleStream doubles(long streamSize, double randomNumberOrigin, + double randomNumberBound) { + if (streamSize < 0L) + throw new IllegalArgumentException(BadSize); + if (!(randomNumberOrigin < randomNumberBound)) + throw new IllegalArgumentException(BadRange); + return StreamSupport.doubleStream + (new RandomDoublesSpliterator + (0L, streamSize, randomNumberOrigin, randomNumberBound), + false); + } + + /** + * Returns an effectively unlimited stream of pseudorandom {@code + * double} values, each conforming to the given origin (inclusive) and bound + * (exclusive). + * + * @implNote This method is implemented to be equivalent to {@code + * doubles(Long.MAX_VALUE, randomNumberOrigin, randomNumberBound)}. + * + * @param randomNumberOrigin the origin (inclusive) of each random value + * @param randomNumberBound the bound (exclusive) of each random value + * @return a stream of pseudorandom {@code double} values, + * each with the given origin (inclusive) and bound (exclusive) + * @throws IllegalArgumentException if {@code randomNumberOrigin} + * is greater than or equal to {@code randomNumberBound} + * @since 1.8 + */ + public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) { + if (!(randomNumberOrigin < randomNumberBound)) + throw new IllegalArgumentException(BadRange); + return StreamSupport.doubleStream + (new RandomDoublesSpliterator + (0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound), + false); + } + + /** + * Spliterator for int streams. We multiplex the four int + * versions into one class by treating a bound less than origin as + * unbounded, and also by treating "infinite" as equivalent to + * Long.MAX_VALUE. For splits, it uses the standard divide-by-two + * approach. The long and double versions of this class are + * identical except for types. + */ + static final class RandomIntsSpliterator implements Spliterator.OfInt { + long index; + final long fence; + final int origin; + final int bound; + RandomIntsSpliterator(long index, long fence, + int origin, int bound) { + this.index = index; this.fence = fence; + this.origin = origin; this.bound = bound; + } + + public RandomIntsSpliterator trySplit() { + long i = index, m = (i + fence) >>> 1; + return (m <= i) ? null : + new RandomIntsSpliterator(i, index = m, origin, bound); + } + + public long estimateSize() { + return fence - index; + } + + public int characteristics() { + return (Spliterator.SIZED | Spliterator.SUBSIZED | + Spliterator.NONNULL | Spliterator.IMMUTABLE); + } + + public boolean tryAdvance(IntConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(ThreadLocalRandom.current().internalNextInt(origin, bound)); + index = i + 1; + return true; + } + return false; + } + + public void forEachRemaining(IntConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + int o = origin, b = bound; + ThreadLocalRandom rng = ThreadLocalRandom.current(); + do { + consumer.accept(rng.internalNextInt(o, b)); + } while (++i < f); + } + } + } + + /** + * Spliterator for long streams. + */ + static final class RandomLongsSpliterator implements Spliterator.OfLong { + long index; + final long fence; + final long origin; + final long bound; + RandomLongsSpliterator(long index, long fence, + long origin, long bound) { + this.index = index; this.fence = fence; + this.origin = origin; this.bound = bound; + } + + public RandomLongsSpliterator trySplit() { + long i = index, m = (i + fence) >>> 1; + return (m <= i) ? null : + new RandomLongsSpliterator(i, index = m, origin, bound); + } + + public long estimateSize() { + return fence - index; + } + + public int characteristics() { + return (Spliterator.SIZED | Spliterator.SUBSIZED | + Spliterator.NONNULL | Spliterator.IMMUTABLE); + } + + public boolean tryAdvance(LongConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(ThreadLocalRandom.current().internalNextLong(origin, bound)); + index = i + 1; + return true; + } + return false; + } + + public void forEachRemaining(LongConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + long o = origin, b = bound; + ThreadLocalRandom rng = ThreadLocalRandom.current(); + do { + consumer.accept(rng.internalNextLong(o, b)); + } while (++i < f); + } + } + + } + + /** + * Spliterator for double streams. + */ + static final class RandomDoublesSpliterator implements Spliterator.OfDouble { + long index; + final long fence; + final double origin; + final double bound; + RandomDoublesSpliterator(long index, long fence, + double origin, double bound) { + this.index = index; this.fence = fence; + this.origin = origin; this.bound = bound; + } + + public RandomDoublesSpliterator trySplit() { + long i = index, m = (i + fence) >>> 1; + return (m <= i) ? null : + new RandomDoublesSpliterator(i, index = m, origin, bound); + } + + public long estimateSize() { + return fence - index; + } + + public int characteristics() { + return (Spliterator.SIZED | Spliterator.SUBSIZED | + Spliterator.NONNULL | Spliterator.IMMUTABLE); + } + + public boolean tryAdvance(DoubleConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + consumer.accept(ThreadLocalRandom.current().internalNextDouble(origin, bound)); + index = i + 1; + return true; + } + return false; + } + + public void forEachRemaining(DoubleConsumer consumer) { + if (consumer == null) throw new NullPointerException(); + long i = index, f = fence; + if (i < f) { + index = f; + double o = origin, b = bound; + ThreadLocalRandom rng = ThreadLocalRandom.current(); + do { + consumer.accept(rng.internalNextDouble(o, b)); + } while (++i < f); + } + } + } + + // Within-package utilities /* @@ -401,23 +1009,26 @@ public class ThreadLocalRandom extends Random { */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("rnd", long.class), - new ObjectStreamField("initialized", boolean.class) + new ObjectStreamField("initialized", boolean.class), }; /** * Saves the {@code ThreadLocalRandom} to a stream (that is, serializes it). + * @param s the stream + * @throws java.io.IOException if an I/O error occurs */ - private void writeObject(java.io.ObjectOutputStream out) + private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { - java.io.ObjectOutputStream.PutField fields = out.putFields(); + java.io.ObjectOutputStream.PutField fields = s.putFields(); fields.put("rnd", UNSAFE.getLong(Thread.currentThread(), SEED)); fields.put("initialized", true); - out.writeFields(); + s.writeFields(); } /** * Returns the {@link #current() current} thread's {@code ThreadLocalRandom}. + * @return the {@link #current() current} thread's {@code ThreadLocalRandom} */ private Object readResolve() { return current(); diff --git a/src/share/classes/java/util/concurrent/locks/StampedLock.java b/src/share/classes/java/util/concurrent/locks/StampedLock.java index 1506e5a4e46ba97e72212e459006d0ca13091471..5fe20b6a578c6337eb63f978793e847cd9a07b88 100644 --- a/src/share/classes/java/util/concurrent/locks/StampedLock.java +++ b/src/share/classes/java/util/concurrent/locks/StampedLock.java @@ -226,7 +226,11 @@ public class StampedLock implements java.io.Serializable { * incoming reader arrives while read lock is held but there is a * queued writer, this incoming reader is queued. (This rule is * responsible for some of the complexity of method acquireRead, - * but without it, the lock becomes highly unfair.) + * but without it, the lock becomes highly unfair.) Method release + * does not (and sometimes cannot) itself wake up cowaiters. This + * is done by the primary thread, but helped by any other threads + * with nothing better to do in methods acquireRead and + * acquireWrite. * * These rules apply to threads actually queued. All tryLock forms * opportunistically try to acquire locks regardless of preference @@ -267,11 +271,14 @@ public class StampedLock implements java.io.Serializable { /** Number of processors, for spin control */ private static final int NCPU = Runtime.getRuntime().availableProcessors(); - /** Maximum number of retries before blocking on acquisition */ + /** Maximum number of retries before enqueuing on acquisition */ private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0; + /** Maximum number of retries before blocking at head on acquisition */ + private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0; + /** Maximum number of retries before re-blocking */ - private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 12 : 0; + private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0; /** The period for yielding when waiting for overflow spinlock */ private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1 @@ -415,8 +422,8 @@ public class StampedLock implements java.io.Serializable { * @return a stamp that can be used to unlock or convert mode */ public long readLock() { - long s, next; // bypass acquireRead on fully unlocked case only - return ((((s = state) & ABITS) == 0L && + long s = state, next; // bypass acquireRead on common uncontended case + return ((whead == wtail && (s & ABITS) < RFULL && U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ? next : acquireRead(false, 0L)); } @@ -1012,17 +1019,8 @@ public class StampedLock implements java.io.Serializable { if (t.status <= 0) q = t; } - if (q != null) { - for (WNode r = q;;) { // release co-waiters too - if ((w = r.thread) != null) { - r.thread = null; - 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 @@ public class StampedLock implements java.io.Serializable { private long acquireWrite(boolean interruptible, long deadline) { WNode node = null, p; for (int spins = -1;;) { // spin while enqueuing - long s, ns; - if (((s = state) & ABITS) == 0L) { + long m, s, ns; + if ((m = (s = state) & ABITS) == 0L) { if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT)) return ns; } + else if (spins < 0) + spins = (m == WBIT && wtail == whead) ? SPINS : 0; else if (spins > 0) { if (LockSupport.nextSecondarySeed() >= 0) --spins; } else if ((p = wtail) == null) { // initialize queue - WNode h = new WNode(WMODE, null); - if (U.compareAndSwapObject(this, WHEAD, null, h)) - wtail = h; + WNode hd = new WNode(WMODE, null); + if (U.compareAndSwapObject(this, WHEAD, null, hd)) + wtail = hd; } - else if (spins < 0) - spins = (p == whead) ? SPINS : 0; else if (node == null) node = new WNode(WMODE, p); else if (node.prev != p) @@ -1064,14 +1062,18 @@ public class StampedLock implements java.io.Serializable { } } - for (int spins = SPINS;;) { - WNode np, pp; int ps; long s, ns; Thread w; - while ((np = node.prev) != p && np != null) - (p = np).next = node; // stale - if (whead == p) { + for (int spins = -1;;) { + WNode h, np, pp; int ps; + if ((h = whead) == p) { + if (spins < 0) + spins = HEAD_SPINS; + else if (spins < MAX_HEAD_SPINS) + spins <<= 1; for (int k = spins;;) { // spin at head + long s, ns; if (((s = state) & ABITS) == 0L) { - if (U.compareAndSwapLong(this, STATE, s, ns = s+WBIT)) { + if (U.compareAndSwapLong(this, STATE, s, + ns = s + WBIT)) { whead = node; node.prev = null; return ns; @@ -1081,33 +1083,45 @@ public class StampedLock implements java.io.Serializable { --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 @@ public class StampedLock implements java.io.Serializable { * @return next state, or INTERRUPTED */ private long acquireRead(boolean interruptible, long deadline) { - WNode node = null, group = null, p; + WNode node = null, p; for (int spins = -1;;) { - for (;;) { - long s, m, ns; WNode h, q; Thread w; // anti-barging guard - if (group == null && (h = whead) != null && - (q = h.next) != null && q.mode != RMODE) - break; - 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 (spins > 0) { - if (LockSupport.nextSecondarySeed() >= 0) - --spins; } - else if ((p = wtail) == null) { - WNode h = new WNode(WMODE, null); - if (U.compareAndSwapObject(this, WHEAD, null, h)) - wtail = h; + if (p == null) { // initialize queue + WNode hd = new WNode(WMODE, null); + if (U.compareAndSwapObject(this, WHEAD, null, hd)) + wtail = hd; } - else if (spins < 0) - spins = (p == whead) ? SPINS : 0; else if (node == null) - node = new WNode(WMODE, p); - else if (node.prev != p) - node.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;;) { + 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 (!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 @@ public class StampedLock implements java.io.Serializable { if (node != null && group != null) { Thread w; node.status = CANCELLED; - node.thread = null; // unsplice cancelled nodes from group for (WNode p = group, q; (q = p.cowait) != null;) { - if (q.status == CANCELLED) - U.compareAndSwapObject(p, WNEXT, q, q.next); + if (q.status == CANCELLED) { + U.compareAndSwapObject(p, WCOWAIT, q, q.cowait); + p = group; // restart + } else p = q; } if (group == node) { - WNode r; // detach and wake up uncancelled co-waiters - while ((r = node.cowait) != null) { - if (U.compareAndSwapObject(node, WCOWAIT, r, r.cowait) && - (w = r.thread) != null) { - r.thread = null; - U.unpark(w); - } + for (WNode r = group.cowait; r != null; r = r.cowait) { + if ((w = r.thread) != null) + U.unpark(w); // wake up uncancelled co-waiters } for (WNode pred = node.prev; pred != null; ) { // unsplice WNode succ, pp; // find valid successor diff --git a/src/share/classes/java/util/jar/JarVerifier.java b/src/share/classes/java/util/jar/JarVerifier.java index 73748c1083d5662c4e424698658dc25ed682cc12..30459e543240202ae326bbd773ef43cdb0aee558 100644 --- a/src/share/classes/java/util/jar/JarVerifier.java +++ b/src/share/classes/java/util/jar/JarVerifier.java @@ -32,6 +32,7 @@ import java.security.*; import java.security.cert.CertificateException; import java.util.zip.ZipEntry; +import sun.misc.JarIndex; import sun.security.util.ManifestDigester; import sun.security.util.ManifestEntryVerifier; import sun.security.util.SignatureFileVerifier; @@ -139,7 +140,8 @@ class JarVerifier { return; } - if (uname.equals(JarFile.MANIFEST_NAME)) { + if (uname.equals(JarFile.MANIFEST_NAME) || + uname.equals(JarIndex.INDEX_NAME)) { return; } diff --git a/src/share/classes/java/util/logging/Logger.java b/src/share/classes/java/util/logging/Logger.java index 1c959ecd6a1c42208b0d7f214e97ec537f44c5b4..a7f0cc2cd4aecbef9a8c57ccc215dfc97f1a8d8f 100644 --- a/src/share/classes/java/util/logging/Logger.java +++ b/src/share/classes/java/util/logging/Logger.java @@ -457,13 +457,15 @@ public class Logger { * of the subsystem, such as java.net * or javax.swing * @param resourceBundleName name of ResourceBundle to be used for localizing - * messages for this logger. May be null if none of - * the messages require localization. + * messages for this logger. May be {@code null} + * if none of the messages require localization. * @return a suitable Logger * @throws MissingResourceException if the resourceBundleName is non-null and * no corresponding resource can be found. * @throws IllegalArgumentException if the Logger already exists and uses - * a different resource bundle name. + * a different resource bundle name; or if + * {@code resourceBundleName} is {@code null} but the named + * logger has a resource bundle set. * @throws NullPointerException if the name is null. */ @@ -1731,10 +1733,6 @@ public class Logger { // Synchronized to prevent races in setting the fields. private synchronized void setupResourceInfo(String name, Class callersClass) { - if (name == null) { - return; - } - if (resourceBundleName != null) { // this Logger already has a ResourceBundle @@ -1748,6 +1746,10 @@ public class Logger { resourceBundleName + " != " + name); } + if (name == null) { + return; + } + setCallersClassLoaderRef(callersClass); if (findResourceBundle(name, true) == null) { // We've failed to find an expected ResourceBundle. diff --git a/src/share/classes/java/util/regex/Pattern.java b/src/share/classes/java/util/regex/Pattern.java index d7b800e32586cf42727eabbd87c6b56766c15960..1dc72c10cd32a1df9ca27c6bf1482130029302cd 100644 --- a/src/share/classes/java/util/regex/Pattern.java +++ b/src/share/classes/java/util/regex/Pattern.java @@ -219,7 +219,7 @@ import java.util.stream.StreamSupport; * *   * Classes for Unicode scripts, blocks, categories and binary properties - * * {@code \p{IsLatin}} + * {@code \p{IsLatin}} * A Latin script character (script) * {@code \p{InGreek}} * A character in the Greek block (block) @@ -4456,16 +4456,16 @@ loop: for(int x=0, offset=0; x { throw new IllegalStateException(String.format("Duplicate key %s", u)); }; } + @SuppressWarnings("unchecked") + private static Function castingIdentity() { + return i -> (R) i; + } + /** * Simple implementation class for {@code Collector}. * @@ -166,7 +171,7 @@ public final class Collectors { BiConsumer accumulator, BinaryOperator combiner, Set characteristics) { - this(supplier, accumulator, combiner, i -> (R) i, characteristics); + this(supplier, accumulator, combiner, castingIdentity(), characteristics); } @Override @@ -209,7 +214,7 @@ public final class Collectors { */ public static > Collector toCollection(Supplier collectionFactory) { - return new CollectorImpl<>(collectionFactory, Collection::add, + return new CollectorImpl<>(collectionFactory, Collection::add, (r1, r2) -> { r1.addAll(r2); return r1; }, CH_ID); } @@ -1046,30 +1051,23 @@ public final class Collectors { public static Collector> partitioningBy(Predicate predicate, Collector downstream) { - @SuppressWarnings("unchecked") - BiConsumer downstreamAccumulator = (BiConsumer) downstream.accumulator(); - BiConsumer, T> accumulator = (result, t) -> { - Partition asPartition = ((Partition) result); - downstreamAccumulator.accept(predicate.test(t) ? asPartition.forTrue : asPartition.forFalse, t); - }; + BiConsumer downstreamAccumulator = downstream.accumulator(); + BiConsumer, T> accumulator = (result, t) -> + downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t); BinaryOperator op = downstream.combiner(); - BinaryOperator> merger = (m1, m2) -> { - Partition left = (Partition) m1; - Partition right = (Partition) m2; - return new Partition<>(op.apply(left.forTrue, right.forTrue), - op.apply(left.forFalse, right.forFalse)); - }; - Supplier> supplier = () -> new Partition<>(downstream.supplier().get(), - downstream.supplier().get()); + BinaryOperator> merger = (left, right) -> + new Partition<>(op.apply(left.forTrue, right.forTrue), + op.apply(left.forFalse, right.forFalse)); + Supplier> 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> finisher = (Map par) -> { - Partition asAPartition = (Partition) par; - return new Partition<>(downstream.finisher().apply(asAPartition.forTrue), - downstream.finisher().apply(asAPartition.forFalse)); - }; + Function, Map> finisher = par -> + new Partition<>(downstream.finisher().apply(par.forTrue), + downstream.finisher().apply(par.forFalse)); return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID); } } diff --git a/src/share/classes/java/util/stream/DistinctOps.java b/src/share/classes/java/util/stream/DistinctOps.java index 69d231f88f5cb37ca490de26e0e01f5e7aa2431e..1c4dfee5d6715107571063bfad9389adc67ef30f 100644 --- a/src/share/classes/java/util/stream/DistinctOps.java +++ b/src/share/classes/java/util/stream/DistinctOps.java @@ -101,7 +101,7 @@ final class DistinctOps { if (StreamOpFlag.DISTINCT.isKnown(flags)) { return sink; } else if (StreamOpFlag.SORTED.isKnown(flags)) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { boolean seenNull; T lastSeen; @@ -132,7 +132,7 @@ final class DistinctOps { } }; } else { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { Set seen; @Override diff --git a/src/share/classes/java/util/stream/DoublePipeline.java b/src/share/classes/java/util/stream/DoublePipeline.java index 44c8ff0f5e7a1f8c74e27c0e3e84e4d0dd7678b3..f894fa0abb917e6f6223405720704cd2a37318b1 100644 --- a/src/share/classes/java/util/stream/DoublePipeline.java +++ b/src/share/classes/java/util/stream/DoublePipeline.java @@ -191,7 +191,7 @@ abstract class DoublePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedDouble(sink) { + return new Sink.ChainedDouble(sink) { @Override public void accept(double t) { downstream.accept(mapper.applyAsDouble(t)); @@ -208,9 +208,8 @@ abstract class DoublePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedDouble(sink) { + return new Sink.ChainedDouble(sink) { @Override - @SuppressWarnings("unchecked") public void accept(double t) { downstream.accept(mapper.apply(t)); } @@ -226,7 +225,7 @@ abstract class DoublePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedDouble(sink) { + return new Sink.ChainedDouble(sink) { @Override public void accept(double t) { downstream.accept(mapper.applyAsInt(t)); @@ -243,7 +242,7 @@ abstract class DoublePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedDouble(sink) { + return new Sink.ChainedDouble(sink) { @Override public void accept(double t) { downstream.accept(mapper.applyAsLong(t)); @@ -259,7 +258,7 @@ abstract class DoublePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedDouble(sink) { + return new Sink.ChainedDouble(sink) { @Override public void begin(long size) { downstream.begin(-1); @@ -296,7 +295,7 @@ abstract class DoublePipeline StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedDouble(sink) { + return new Sink.ChainedDouble(sink) { @Override public void begin(long size) { downstream.begin(-1); @@ -319,7 +318,7 @@ abstract class DoublePipeline 0) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedDouble(sink) { + return new Sink.ChainedDouble(sink) { @Override public void accept(double t) { consumer.accept(t); diff --git a/src/share/classes/java/util/stream/IntPipeline.java b/src/share/classes/java/util/stream/IntPipeline.java index d380e4a3bf589c9708f90bdf71f65f192d9c5c11..f7dc79317d38996bf06616e0859729924511a1a3 100644 --- a/src/share/classes/java/util/stream/IntPipeline.java +++ b/src/share/classes/java/util/stream/IntPipeline.java @@ -189,9 +189,8 @@ abstract class IntPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { + return new Sink.ChainedInt(sink) { @Override - @SuppressWarnings("unchecked") public void accept(int t) { downstream.accept((long) t); } @@ -206,9 +205,8 @@ abstract class IntPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { + return new Sink.ChainedInt(sink) { @Override - @SuppressWarnings("unchecked") public void accept(int t) { downstream.accept((double) t); } @@ -229,7 +227,7 @@ abstract class IntPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { + return new Sink.ChainedInt(sink) { @Override public void accept(int t) { downstream.accept(mapper.applyAsInt(t)); @@ -246,9 +244,8 @@ abstract class IntPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { + return new Sink.ChainedInt(sink) { @Override - @SuppressWarnings("unchecked") public void accept(int t) { downstream.accept(mapper.apply(t)); } @@ -264,7 +261,7 @@ abstract class IntPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { + return new Sink.ChainedInt(sink) { @Override public void accept(int t) { downstream.accept(mapper.applyAsLong(t)); @@ -281,7 +278,7 @@ abstract class IntPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { + return new Sink.ChainedInt(sink) { @Override public void accept(int t) { downstream.accept(mapper.applyAsDouble(t)); @@ -297,7 +294,7 @@ abstract class IntPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { + return new Sink.ChainedInt(sink) { @Override public void begin(long size) { downstream.begin(-1); @@ -334,7 +331,7 @@ abstract class IntPipeline StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { + return new Sink.ChainedInt(sink) { @Override public void begin(long size) { downstream.begin(-1); @@ -357,7 +354,7 @@ abstract class IntPipeline 0) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { + return new Sink.ChainedInt(sink) { @Override public void accept(int t) { consumer.accept(t); diff --git a/src/share/classes/java/util/stream/LongPipeline.java b/src/share/classes/java/util/stream/LongPipeline.java index 083f7bb8b2b5fc3107d7592a812666f70536b0cb..3c199feab59ac4b3ed3637dc66f9f3faba23dc35 100644 --- a/src/share/classes/java/util/stream/LongPipeline.java +++ b/src/share/classes/java/util/stream/LongPipeline.java @@ -186,7 +186,7 @@ abstract class LongPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { + return new Sink.ChainedLong(sink) { @Override public void accept(long t) { downstream.accept((double) t); @@ -208,9 +208,8 @@ abstract class LongPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { + return new Sink.ChainedLong(sink) { @Override - @SuppressWarnings("unchecked") public void accept(long t) { downstream.accept(mapper.applyAsLong(t)); } @@ -226,9 +225,8 @@ abstract class LongPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { + return new Sink.ChainedLong(sink) { @Override - @SuppressWarnings("unchecked") public void accept(long t) { downstream.accept(mapper.apply(t)); } @@ -244,9 +242,8 @@ abstract class LongPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { + return new Sink.ChainedLong(sink) { @Override - @SuppressWarnings("unchecked") public void accept(long t) { downstream.accept(mapper.applyAsInt(t)); } @@ -262,7 +259,7 @@ abstract class LongPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { + return new Sink.ChainedLong(sink) { @Override public void accept(long t) { downstream.accept(mapper.applyAsDouble(t)); @@ -278,7 +275,7 @@ abstract class LongPipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { + return new Sink.ChainedLong(sink) { @Override public void begin(long size) { downstream.begin(-1); @@ -315,7 +312,7 @@ abstract class LongPipeline StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { + return new Sink.ChainedLong(sink) { @Override public void begin(long size) { downstream.begin(-1); @@ -338,7 +335,7 @@ abstract class LongPipeline 0) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { + return new Sink.ChainedLong(sink) { @Override public void accept(long t) { consumer.accept(t); diff --git a/src/share/classes/java/util/stream/ReferencePipeline.java b/src/share/classes/java/util/stream/ReferencePipeline.java index c201950d88c275ac6c953dadc4ee8a5db20d4170..1fffff48b1836e36818e23b7a0ba67eccaff6874 100644 --- a/src/share/classes/java/util/stream/ReferencePipeline.java +++ b/src/share/classes/java/util/stream/ReferencePipeline.java @@ -163,17 +163,16 @@ abstract class ReferencePipeline StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { @Override public void begin(long size) { downstream.begin(-1); } @Override - @SuppressWarnings("unchecked") public void accept(P_OUT u) { if (predicate.test(u)) - downstream.accept((Object) u); + downstream.accept(u); } }; } @@ -188,7 +187,7 @@ abstract class ReferencePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { @Override public void accept(P_OUT u) { downstream.accept(mapper.apply(u)); @@ -205,7 +204,7 @@ abstract class ReferencePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { @Override public void accept(P_OUT u) { downstream.accept(mapper.applyAsInt(u)); @@ -222,7 +221,7 @@ abstract class ReferencePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { @Override public void accept(P_OUT u) { downstream.accept(mapper.applyAsLong(u)); @@ -239,7 +238,7 @@ abstract class ReferencePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { @Override public void accept(P_OUT u) { downstream.accept(mapper.applyAsDouble(u)); @@ -257,14 +256,13 @@ abstract class ReferencePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(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 result = mapper.apply(u); @@ -284,7 +282,7 @@ abstract class ReferencePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { IntConsumer downstreamAsInt = downstream::accept; @Override public void begin(long size) { @@ -311,7 +309,7 @@ abstract class ReferencePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { DoubleConsumer downstreamAsDouble = downstream::accept; @Override public void begin(long size) { @@ -338,7 +336,7 @@ abstract class ReferencePipeline StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { LongConsumer downstreamAsLong = downstream::accept; @Override public void begin(long size) { @@ -364,9 +362,8 @@ abstract class ReferencePipeline 0) { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { @Override - @SuppressWarnings("unchecked") public void accept(P_OUT u) { tee.accept(u); downstream.accept(u); @@ -495,6 +492,7 @@ abstract class ReferencePipeline } @Override + @SuppressWarnings("unchecked") public final R collect(Collector collector) { A container; if (isParallel() diff --git a/src/share/classes/java/util/stream/Sink.java b/src/share/classes/java/util/stream/Sink.java index 987d0e9efa7abd7f1f6d12ab7b7d8bc137985550..d2a366df16ebf29c359d342afbe5579108bccbaf 100644 --- a/src/share/classes/java/util/stream/Sink.java +++ b/src/share/classes/java/util/stream/Sink.java @@ -241,11 +241,10 @@ interface Sink extends Consumer { * implementation of the {@code accept()} method must call the correct * {@code accept()} method on the downstream {@code Sink}. */ - static abstract class ChainedReference implements Sink { - @SuppressWarnings("rawtypes") - protected final Sink downstream; + static abstract class ChainedReference implements Sink { + protected final Sink downstream; - public ChainedReference(Sink downstream) { + public ChainedReference(Sink downstream) { this.downstream = Objects.requireNonNull(downstream); } @@ -274,11 +273,10 @@ interface Sink extends Consumer { * 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 implements Sink.OfInt { + protected final Sink downstream; - public ChainedInt(Sink downstream) { + public ChainedInt(Sink downstream) { this.downstream = Objects.requireNonNull(downstream); } @@ -307,11 +305,10 @@ interface Sink extends Consumer { * 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 implements Sink.OfLong { + protected final Sink downstream; - public ChainedLong(Sink downstream) { + public ChainedLong(Sink downstream) { this.downstream = Objects.requireNonNull(downstream); } @@ -340,11 +337,10 @@ interface Sink extends Consumer { * 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 implements Sink.OfDouble { + protected final Sink downstream; - public ChainedDouble(Sink downstream) { + public ChainedDouble(Sink downstream) { this.downstream = Objects.requireNonNull(downstream); } diff --git a/src/share/classes/java/util/stream/SliceOps.java b/src/share/classes/java/util/stream/SliceOps.java index 09e14f637f458f0a75fd32d9f6d7e3de390a5675..34d55309d2d7e93a0ba2d601ce983ca830b48d1a 100644 --- a/src/share/classes/java/util/stream/SliceOps.java +++ b/src/share/classes/java/util/stream/SliceOps.java @@ -96,6 +96,11 @@ final class SliceOps { } } + @SuppressWarnings("unchecked") + private static IntFunction 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 @@ final class SliceOps { * is to be imposed */ public static Stream makeRef(AbstractPipeline 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(upstream, StreamShape.REFERENCE, - flags(limit)) { + return new ReferencePipeline.StatefulOp(upstream, StreamShape.REFERENCE, + flags(limit)) { Spliterator unorderedSkipLimitSpliterator(Spliterator s, long skip, long limit, long sizeIfKnown) { if (skip <= sizeIfKnown) { @@ -146,7 +151,7 @@ final class SliceOps { // cancellation will be more aggressive cancelling later tasks // if the target slice size has been reached from a given task, // cancellation should also clear local results if any - return new SliceTask<>(this, helper, spliterator, i -> (T[]) new Object[i], skip, limit). + return new SliceTask<>(this, helper, spliterator, castingArray(), skip, limit). invoke().spliterator(); } } @@ -182,7 +187,7 @@ final class SliceOps { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedReference(sink) { + return new Sink.ChainedReference(sink) { long n = skip; long m = limit >= 0 ? limit : Long.MAX_VALUE; @@ -291,7 +296,7 @@ final class SliceOps { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedInt(sink) { + return new Sink.ChainedInt(sink) { long n = skip; long m = limit >= 0 ? limit : Long.MAX_VALUE; @@ -400,7 +405,7 @@ final class SliceOps { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedLong(sink) { + return new Sink.ChainedLong(sink) { long n = skip; long m = limit >= 0 ? limit : Long.MAX_VALUE; @@ -509,7 +514,7 @@ final class SliceOps { @Override Sink opWrapSink(int flags, Sink sink) { - return new Sink.ChainedDouble(sink) { + return new Sink.ChainedDouble(sink) { long n = skip; long m = limit >= 0 ? limit : Long.MAX_VALUE; @@ -560,13 +565,13 @@ final class SliceOps { private volatile boolean completed; - SliceTask(AbstractPipeline op, + SliceTask(AbstractPipeline op, PipelineHelper helper, Spliterator spliterator, IntFunction generator, long offset, long size) { super(helper, spliterator); - this.op = (AbstractPipeline) op; + this.op = op; this.generator = generator; this.targetOffset = offset; this.targetSize = size; diff --git a/src/share/classes/java/util/stream/SortedOps.java b/src/share/classes/java/util/stream/SortedOps.java index 047479a645de5f705778a791d24fcb5fdf7c75d9..9df65e352e28e6a596196f5aa277b01107b01c1f 100644 --- a/src/share/classes/java/util/stream/SortedOps.java +++ b/src/share/classes/java/util/stream/SortedOps.java @@ -129,7 +129,7 @@ final class SortedOps { } @Override - public Sink opWrapSink(int flags, Sink sink) { + public Sink opWrapSink(int flags, Sink sink) { Objects.requireNonNull(sink); // If the input is already naturally sorted and this operation @@ -280,12 +280,12 @@ final class SortedOps { /** * {@link ForkJoinTask} for implementing sort on SIZED reference streams. */ - private static final class SizedRefSortingSink extends Sink.ChainedReference { + private static final class SizedRefSortingSink extends Sink.ChainedReference { private final Comparator comparator; private T[] array; private int offset; - SizedRefSortingSink(Sink sink, Comparator comparator) { + SizedRefSortingSink(Sink sink, Comparator comparator) { super(sink); this.comparator = comparator; } @@ -320,11 +320,11 @@ final class SortedOps { /** * {@link Sink} for implementing sort on reference streams. */ - private static final class RefSortingSink extends Sink.ChainedReference { + private static final class RefSortingSink extends Sink.ChainedReference { private final Comparator comparator; private ArrayList list; - RefSortingSink(Sink sink, Comparator comparator) { + RefSortingSink(Sink sink, Comparator comparator) { super(sink); this.comparator = comparator; } @@ -352,11 +352,11 @@ final class SortedOps { /** * {@link Sink} for implementing sort on SIZED int streams. */ - private static final class SizedIntSortingSink extends Sink.ChainedInt { + private static final class SizedIntSortingSink extends Sink.ChainedInt { private int[] array; private int offset; - SizedIntSortingSink(Sink downstream) { + SizedIntSortingSink(Sink downstream) { super(downstream); } @@ -386,10 +386,10 @@ final class SortedOps { /** * {@link Sink} for implementing sort on int streams. */ - private static final class IntSortingSink extends Sink.ChainedInt { + private static final class IntSortingSink extends Sink.ChainedInt { private SpinedBuffer.OfInt b; - IntSortingSink(Sink sink) { + IntSortingSink(Sink sink) { super(sink); } @@ -417,11 +417,11 @@ final class SortedOps { /** * {@link Sink} for implementing sort on SIZED long streams. */ - private static final class SizedLongSortingSink extends Sink.ChainedLong { + private static final class SizedLongSortingSink extends Sink.ChainedLong { private long[] array; private int offset; - SizedLongSortingSink(Sink downstream) { + SizedLongSortingSink(Sink downstream) { super(downstream); } @@ -451,10 +451,10 @@ final class SortedOps { /** * {@link Sink} for implementing sort on long streams. */ - private static final class LongSortingSink extends Sink.ChainedLong { + private static final class LongSortingSink extends Sink.ChainedLong { private SpinedBuffer.OfLong b; - LongSortingSink(Sink sink) { + LongSortingSink(Sink sink) { super(sink); } @@ -482,11 +482,11 @@ final class SortedOps { /** * {@link Sink} for implementing sort on SIZED double streams. */ - private static final class SizedDoubleSortingSink extends Sink.ChainedDouble { + private static final class SizedDoubleSortingSink extends Sink.ChainedDouble { private double[] array; private int offset; - SizedDoubleSortingSink(Sink downstream) { + SizedDoubleSortingSink(Sink downstream) { super(downstream); } @@ -516,10 +516,10 @@ final class SortedOps { /** * {@link Sink} for implementing sort on double streams. */ - private static final class DoubleSortingSink extends Sink.ChainedDouble { + private static final class DoubleSortingSink extends Sink.ChainedDouble { private SpinedBuffer.OfDouble b; - DoubleSortingSink(Sink sink) { + DoubleSortingSink(Sink sink) { super(sink); } diff --git a/src/share/classes/java/util/zip/ZipOutputStream.java b/src/share/classes/java/util/zip/ZipOutputStream.java index 4072fbed52dce26d275f45dde1d9a73dda9e4d8b..3b76ecaab24bcc8488ddc7d9f423247bfd765b18 100644 --- a/src/share/classes/java/util/zip/ZipOutputStream.java +++ b/src/share/classes/java/util/zip/ZipOutputStream.java @@ -663,6 +663,9 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { while (off + 4 <= len) { int tag = get16(extra, off); int sz = get16(extra, off + 2); + if (sz < 0 || (off + 4 + sz) > len) { + break; + } if (tag == EXTID_EXTT || tag == EXTID_ZIP64) { skipped += (sz + 4); } @@ -684,11 +687,18 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { while (off + 4 <= len) { int tag = get16(extra, off); int sz = get16(extra, off + 2); + if (sz < 0 || (off + 4 + sz) > len) { + writeBytes(extra, off, len - off); + return; + } if (tag != EXTID_EXTT && tag != EXTID_ZIP64) { writeBytes(extra, off, sz + 4); } off += (sz + 4); } + if (off < len) { + writeBytes(extra, off, len - off); + } } } diff --git a/src/share/classes/javax/net/ssl/SNIHostName.java b/src/share/classes/javax/net/ssl/SNIHostName.java index 588a8547e11aadd7e623b1327726423171cf68e4..d5e714144971207afd264844d6b67ab376b405d8 100644 --- a/src/share/classes/javax/net/ssl/SNIHostName.java +++ b/src/share/classes/javax/net/ssl/SNIHostName.java @@ -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 @@ public final class SNIHostName extends SNIServerName { * the * regular expression pattern * 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 diff --git a/src/share/classes/javax/net/ssl/X509KeyManager.java b/src/share/classes/javax/net/ssl/X509KeyManager.java index 5174adfe412a530a05e1d04215055a596883bca8..69ab91ae94d3d4a625f6e9c6bce00108be81fefb 100644 --- a/src/share/classes/javax/net/ssl/X509KeyManager.java +++ b/src/share/classes/javax/net/ssl/X509KeyManager.java @@ -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 @@ import java.net.Socket; *

    *
  • determine the set of aliases that are available for negotiations * based on the criteria presented, - *
  • select the best alias based on + *
  • select the best alias based on * the criteria presented, and *
  • obtain the corresponding key material for given aliases. *
diff --git a/src/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java b/src/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java index 6962f2a43d3d410fb3d348f4db8f4583ed4bdd34..1c033803cc722f2e8259313e954ef3d53ae0b9dd 100644 --- a/src/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java +++ b/src/share/classes/javax/security/auth/kerberos/KerberosPrincipal.java @@ -197,8 +197,7 @@ public final class KerberosPrincipal * {@code KerberosPrincipal} and the two * {@code KerberosPrincipal} instances are equivalent. * More formally two {@code KerberosPrincipal} instances are equal - * if the values returned by {@code getName()} are equal and the - * values returned by {@code getNameType()} are equal. + * if the values returned by {@code getName()} are equal. * * @param other the Object to compare to * @return true if the Object passed in represents the same principal @@ -211,15 +210,10 @@ public final class KerberosPrincipal if (! (other instanceof KerberosPrincipal)) { return false; - } else { - String myFullName = getName(); - String otherFullName = ((KerberosPrincipal) other).getName(); - if (nameType == ((KerberosPrincipal)other).nameType && - myFullName.equals(otherFullName)) { - return true; - } } - return false; + String myFullName = getName(); + String otherFullName = ((KerberosPrincipal) other).getName(); + return myFullName.equals(otherFullName); } /** diff --git a/src/share/classes/sun/misc/Sort.java b/src/share/classes/sun/misc/Sort.java deleted file mode 100644 index adf8e78ff2c45d67ca30a64cedf48d634546776e..0000000000000000000000000000000000000000 --- a/src/share/classes/sun/misc/Sort.java +++ /dev/null @@ -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); - } -} diff --git a/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java b/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java index 264b200dee43e0ad2640e6bdfd38fd5aa59d15e8..22e005df9693c9ca0c58a4ac131a059f9189f2f6 100644 --- a/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java +++ b/src/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java @@ -193,9 +193,4 @@ abstract class AbstractPollSelectorImpl if (!selch.isOpen() && !selch.isRegistered()) ((SelChImpl)selch).kill(); } - - static { - Util.load(); - } - } diff --git a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java index b99750c4c379aa987b63650ebdf55255e2e11279..2cda6fa1527f375588ff00c2299202413f068813 100644 --- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -1138,7 +1138,7 @@ class DatagramChannelImpl throws IOException; static { - Util.load(); + IOUtil.load(); initIDs(); } diff --git a/src/share/classes/sun/nio/ch/FileChannelImpl.java b/src/share/classes/sun/nio/ch/FileChannelImpl.java index ac9be90f2106a6c9a73346eca130d68f6fc54254..b464ecc854a137d35e76fdf15f66273acdf53bf2 100644 --- a/src/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/src/share/classes/sun/nio/ch/FileChannelImpl.java @@ -1162,7 +1162,7 @@ public class FileChannelImpl private static native long initIDs(); static { - Util.load(); + IOUtil.load(); allocationGranularity = initIDs(); } diff --git a/src/share/classes/sun/nio/ch/IOUtil.java b/src/share/classes/sun/nio/ch/IOUtil.java index 6f45da73d1060e499f15cfd3fd81321ce20b1796..ba5449eac707697797458c3e25bc1651f285c75c 100644 --- a/src/share/classes/sun/nio/ch/IOUtil.java +++ b/src/share/classes/sun/nio/ch/IOUtil.java @@ -347,9 +347,23 @@ public class IOUtil { static native void initIDs(); + /** + * Used to trigger loading of native libraries + */ + public static void load() { } + static { - // Note that IOUtil.initIDs is called from within Util.load. - Util.load(); + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + System.loadLibrary("net"); + System.loadLibrary("nio"); + return null; + } + }); + + initIDs(); + IOV_MAX = iovMax(); } diff --git a/src/share/classes/sun/nio/ch/Net.java b/src/share/classes/sun/nio/ch/Net.java index 2b68f963ff52bcee01af2e8bd812be70297b2f51..2e2640290c6a1d21c2e92665db0017a5134ce45c 100644 --- a/src/share/classes/sun/nio/ch/Net.java +++ b/src/share/classes/sun/nio/ch/Net.java @@ -582,7 +582,7 @@ public class Net { private static native void initIDs(); static { - Util.load(); + IOUtil.load(); initIDs(); } diff --git a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index 3b3969cc1589af1da2b3b95b6fa3253d77072e8f..8429442356a3d63dde3958a782d1e824f7047551 100644 --- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -416,7 +416,7 @@ class ServerSocketChannelImpl private static native void initIDs(); static { - Util.load(); + IOUtil.load(); initIDs(); nd = new SocketDispatcher(); } diff --git a/src/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/share/classes/sun/nio/ch/SocketChannelImpl.java index 6959c17780d2d9619aaed42fcd252e0ff50d9737..806168392e935c980ed1d5ad6622f6d232e8cebd 100644 --- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -1024,7 +1024,7 @@ class SocketChannelImpl throws IOException; static { - Util.load(); + IOUtil.load(); nd = new SocketDispatcher(); } diff --git a/src/share/classes/sun/nio/ch/Util.java b/src/share/classes/sun/nio/ch/Util.java index 1904ca58824941c11fe6d39fd63e76094d373256..772f1492a473feab0807da935ee155af2097df24 100644 --- a/src/share/classes/sun/nio/ch/Util.java +++ b/src/share/classes/sun/nio/ch/Util.java @@ -401,30 +401,4 @@ public class Util { return bugLevel.equals(bl); } - - - // -- Initialization -- - - private static boolean loaded = false; - - public static void load() { - synchronized (Util.class) { - if (loaded) - return; - loaded = true; - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - 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(); - } - } - } diff --git a/src/share/classes/sun/tools/jconsole/ConnectDialog.java b/src/share/classes/sun/tools/jconsole/ConnectDialog.java index ea3f8366766fb11dec2b67c235b3ed44e3c422cf..3198fd6cd6a1f29dc0066fb6f1f3c040a957bca6 100644 --- a/src/share/classes/sun/tools/jconsole/ConnectDialog.java +++ b/src/share/classes/sun/tools/jconsole/ConnectDialog.java @@ -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 class ConnectDialog extends InternalDialog public void revalidate() { // Adjust some colors + Color disabledForeground = UIManager.getColor("Label.disabledForeground"); + if (disabledForeground == null) { + // fall back for Nimbus that doesn't support 'Label.disabledForeground' + disabledForeground = UIManager.getColor("Label.disabledText"); + } hintTextColor = - ensureContrast(UIManager.getColor("Label.disabledForeground"), + ensureContrast(disabledForeground, UIManager.getColor("Panel.background")); disabledTableCellColor = ensureContrast(new Color(0x808080), diff --git a/src/share/classes/sun/tools/jconsole/JConsole.java b/src/share/classes/sun/tools/jconsole/JConsole.java index 46d9504dc15940be71201f231c5520341e250b1a..cdb78f94ec933b343c3fcbe206564f546f93b0ba 100644 --- a/src/share/classes/sun/tools/jconsole/JConsole.java +++ b/src/share/classes/sun/tools/jconsole/JConsole.java @@ -858,6 +858,10 @@ public class JConsole extends JFrame try { updateInterval = Integer.parseInt(arg.substring(10)) * 1000; + if (updateInterval <= 0) { + usage(); + return; + } } catch (NumberFormatException ex) { usage(); return; diff --git a/src/share/classes/sun/tools/jconsole/Messages.java b/src/share/classes/sun/tools/jconsole/Messages.java index 0e5fd76bd209879b8b5c68ddf488294d6d25b9ae..0a3a63e85ca2a606a195c64b0d56573155dd6d16 100644 --- a/src/share/classes/sun/tools/jconsole/Messages.java +++ b/src/share/classes/sun/tools/jconsole/Messages.java @@ -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 @@ final public class Messages { public static String HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME; public static String HELP_ABOUT_DIALOG_MASTHEAD_TITLE; public static String HELP_ABOUT_DIALOG_TITLE; - public static String HELP_ABOUT_DIALOG_USER_GUIDE_LINK; public static String HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL; public static String HELP_MENU_ABOUT_TITLE; public static String HELP_MENU_USER_GUIDE_TITLE; @@ -272,6 +271,7 @@ final public class Messages { public static String THREADS; public static String THREAD_TAB_THREAD_INFO_ACCESSIBLE_NAME; public static String THREAD_TAB_THREAD_PLOTTER_ACCESSIBLE_NAME; + public static String THREAD_TAB_INITIAL_STACK_TRACE_MESSAGE; public static String THRESHOLD; public static String TILE; public static String TIME_RANGE_COLON; diff --git a/src/share/classes/sun/tools/jconsole/Plotter.java b/src/share/classes/sun/tools/jconsole/Plotter.java index 793b0ea263d9fdb1fd592fdbc6935afcece78542..acfd005dd0b730359c3512ea5ce980f56bbea512 100644 --- a/src/share/classes/sun/tools/jconsole/Plotter.java +++ b/src/share/classes/sun/tools/jconsole/Plotter.java @@ -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 class Plotter extends JComponent public void paintComponent(Graphics g) { super.paintComponent(g); + int width = getWidth()-rightMargin-leftMargin-10; + int height = getHeight()-topMargin-bottomMargin; + if (width <= 0 || height <= 0) { + // not enough room to paint anything + return; + } + Color oldColor = g.getColor(); Font oldFont = g.getFont(); Color fg = getForeground(); diff --git a/src/share/classes/sun/tools/jconsole/ThreadTab.java b/src/share/classes/sun/tools/jconsole/ThreadTab.java index 354f351f75083f5ce9c5be2f1e413481c78f8512..6cf710a2dff48ae786e11904cecee13392389b86 100644 --- a/src/share/classes/sun/tools/jconsole/ThreadTab.java +++ b/src/share/classes/sun/tools/jconsole/ThreadTab.java @@ -595,6 +595,8 @@ class ThreadTab extends Tab implements ActionListener, DocumentListener, ListSel setBorder(thinEmptyBorder); + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + textArea.setText(Messages.THREAD_TAB_INITIAL_STACK_TRACE_MESSAGE); addListSelectionListener(ThreadTab.this); setCellRenderer(new DefaultListCellRenderer() { public Component getListCellRendererComponent(JList list, Object value, int index, diff --git a/src/share/classes/sun/tools/jconsole/VMPanel.java b/src/share/classes/sun/tools/jconsole/VMPanel.java index b7a0f5b410bb503e3559459f30bb2c70ae72072c..1561b9cc5bb9c896fe87d33294a646b8d167d8a9 100644 --- a/src/share/classes/sun/tools/jconsole/VMPanel.java +++ b/src/share/classes/sun/tools/jconsole/VMPanel.java @@ -153,9 +153,11 @@ public class VMPanel extends JTabbedPane implements PropertyChangeListener { // in order to reserve space for the connect toggle. public void setUI(TabbedPaneUI ui) { Insets insets = (Insets) UIManager.getLookAndFeelDefaults().get("TabbedPane.tabAreaInsets"); - 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); } diff --git a/src/share/classes/sun/tools/jconsole/resources/messages.properties b/src/share/classes/sun/tools/jconsole/resources/messages.properties index ef0b4f136e4890fc2cf25f308d6f9493efd2ffd5..832621731b9c35857ed4f723e21fad81d5018901 100644 --- a/src/share/classes/sun/tools/jconsole/resources/messages.properties +++ b/src/share/classes/sun/tools/jconsole/resources/messages.properties @@ -104,7 +104,6 @@ HELP_ABOUT_DIALOG_JAVA_VERSION=Java VM version:
{0} HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME=Masthead Graphic HELP_ABOUT_DIALOG_MASTHEAD_TITLE=About JConsole HELP_ABOUT_DIALOG_TITLE=JConsole: About -HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole &User Guide:
{0} HELP_ABOUT_DIALOG_USER_GUIDE_LINK_URL=http://docs.oracle.com/javase/{0}/docs/technotes/guides/management/jconsole.html HELP_MENU_ABOUT_TITLE=&About JConsole HELP_MENU_USER_GUIDE_TITLE=Online &User Guide @@ -230,6 +229,7 @@ SUMMARY_TAB_VM_VERSION={0} version {1} THREADS=Threads THREAD_TAB_THREAD_INFO_ACCESSIBLE_NAME=Thread Information THREAD_TAB_THREAD_PLOTTER_ACCESSIBLE_NAME=Chart for number of threads. +THREAD_TAB_INITIAL_STACK_TRACE_MESSAGE=[No thread selected] THRESHOLD=Threshold TILE=&Tile TIME_RANGE_COLON=&Time Range: diff --git a/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties b/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties index 9cc5df8fad820ddb8f90e7c1e23556c490947fda..c66ace770351e65d2bbdd2608f08c3c49e12c135 100644 --- a/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties +++ b/src/share/classes/sun/tools/jconsole/resources/messages_ja.properties @@ -104,7 +104,6 @@ HELP_ABOUT_DIALOG_JAVA_VERSION=Java VM\u30D0\u30FC\u30B8\u30E7\u30F3:
{0} HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME=\u30DE\u30B9\u30C8\u30D8\u30C3\u30C9\u56F3\u5F62 HELP_ABOUT_DIALOG_MASTHEAD_TITLE=JConsole\u306B\u3064\u3044\u3066 HELP_ABOUT_DIALOG_TITLE=JConsole: \u8A73\u7D30 -HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole\u30E6\u30FC\u30B6\u30FC\u30FB\u30AC\u30A4\u30C9(&U):
{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) diff --git a/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties b/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties index d654392edf288ebea98e6ea518b953de5f88da63..3f782adc620830377f42e12228b69e77c4669c64 100644 --- a/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties +++ b/src/share/classes/sun/tools/jconsole/resources/messages_zh_CN.properties @@ -104,7 +104,6 @@ HELP_ABOUT_DIALOG_JAVA_VERSION=Java VM \u7248\u672C:
{0} HELP_ABOUT_DIALOG_MASTHEAD_ACCESSIBLE_NAME=\u62A5\u5934\u56FE HELP_ABOUT_DIALOG_MASTHEAD_TITLE=\u5173\u4E8E JConsole HELP_ABOUT_DIALOG_TITLE=JConsole: \u5173\u4E8E -HELP_ABOUT_DIALOG_USER_GUIDE_LINK=JConsole \u7528\u6237\u6307\u5357(&U):
{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) diff --git a/src/share/lib/security/java.security-linux b/src/share/lib/security/java.security-linux index 2686cae4c4f549de06f6b52197e8388ef5ec4c88..2c5f5f6c32ad69c60af2f228663d1752176c7b74 100644 --- a/src/share/lib/security/java.security-linux +++ b/src/share/lib/security/java.security-linux @@ -181,6 +181,7 @@ package.access=sun.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.,\ + com.sun.media.sound.,\ com.sun.proxy.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ @@ -225,6 +226,7 @@ package.definition=sun.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.,\ + com.sun.media.sound.,\ com.sun.proxy.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ diff --git a/src/share/lib/security/java.security-macosx b/src/share/lib/security/java.security-macosx index 7ea2ee18735e5b183ea339b3fb535b66bb1ea804..44791b241f4427aa3a242a5366af8ce6e438abbe 100644 --- a/src/share/lib/security/java.security-macosx +++ b/src/share/lib/security/java.security-macosx @@ -182,6 +182,7 @@ package.access=sun.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.,\ + com.sun.media.sound.,\ com.sun.proxy.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ @@ -226,6 +227,7 @@ package.definition=sun.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.,\ + com.sun.media.sound.,\ com.sun.proxy.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ diff --git a/src/share/lib/security/java.security-solaris b/src/share/lib/security/java.security-solaris index be885d3b187b997139f140ba6aae83be3ca0f326..a6ce253df8aa2d531c611d01c9ab0fed32b1ceae 100644 --- a/src/share/lib/security/java.security-solaris +++ b/src/share/lib/security/java.security-solaris @@ -183,6 +183,7 @@ package.access=sun.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.,\ + com.sun.media.sound.,\ com.sun.proxy.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ @@ -226,6 +227,7 @@ package.definition=sun.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.,\ + com.sun.media.sound.,\ com.sun.proxy.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ diff --git a/src/share/lib/security/java.security-windows b/src/share/lib/security/java.security-windows index c06a56156ae1163deb341176d7c3e8098d747594..cca53ae396180517d3a49404bdd29f23f43fa86e 100644 --- a/src/share/lib/security/java.security-windows +++ b/src/share/lib/security/java.security-windows @@ -182,6 +182,7 @@ package.access=sun.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.,\ + com.sun.media.sound.,\ com.sun.proxy.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ @@ -226,6 +227,7 @@ package.definition=sun.,\ com.sun.imageio.,\ com.sun.istack.internal.,\ com.sun.jmx.,\ + com.sun.media.sound.,\ com.sun.proxy.,\ com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.regexp.internal.,\ diff --git a/src/share/native/common/check_code.c b/src/share/native/common/check_code.c index e1170293f074e59d7fd7b31e1805b200009ff440..6a114f1f02b10fe47b060420e04381fe441d9d75 100644 --- a/src/share/native/common/check_code.c +++ b/src/share/native/common/check_code.c @@ -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 diff --git a/src/solaris/classes/sun/nio/ch/DatagramDispatcher.java b/src/solaris/classes/sun/nio/ch/DatagramDispatcher.java index 64d4c313a060a64a345e2a9f2415333ca4fa75a4..079529e5bb4cc3e8ed93c87c75487066818f7f41 100644 --- a/src/solaris/classes/sun/nio/ch/DatagramDispatcher.java +++ b/src/solaris/classes/sun/nio/ch/DatagramDispatcher.java @@ -36,7 +36,7 @@ import java.net.*; class DatagramDispatcher extends NativeDispatcher { static { - Util.load(); + IOUtil.load(); } int read(FileDescriptor fd, long address, int len) throws IOException { diff --git a/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java b/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java index 3151b227b8bfe773c9e94267d874dacb0397c5a7..df30e2924f2d9bfc10c8142de279817a30b2d1fd 100644 --- a/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java +++ b/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java @@ -316,4 +316,8 @@ class DevPollArrayWrapper { private native int poll0(long pollAddress, int numfds, long timeout, int wfd); private static native void interrupt(int fd); + + static { + IOUtil.load(); + } } diff --git a/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java b/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java index e151051ecea17ff3dacc4802e7b378c82ae5088c..b0d6a33cbc4a43f2d3442a4a47be2e2ef625e799 100644 --- a/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java +++ b/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java @@ -196,9 +196,4 @@ class DevPollSelectorImpl } return this; } - - static { - Util.load(); - } - } diff --git a/src/solaris/classes/sun/nio/ch/EPoll.java b/src/solaris/classes/sun/nio/ch/EPoll.java index 3300f962ae02a4003d569a57230dba365e6fb3d0..f0a8d7e3fd9d8dbd78af6ced7d48d223c060ddfb 100644 --- a/src/solaris/classes/sun/nio/ch/EPoll.java +++ b/src/solaris/classes/sun/nio/ch/EPoll.java @@ -113,6 +113,6 @@ class EPoll { throws IOException; static { - Util.load(); + IOUtil.load(); } } diff --git a/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java b/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java index 3b59a06ac03400edf18d161eb1aaf200e76f51c1..a73d3c2dff1a4c1fb85e770b8e56b2b0de47bb70 100644 --- a/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java +++ b/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java @@ -318,6 +318,7 @@ class EPollArrayWrapper { } static { + IOUtil.load(); init(); } diff --git a/src/solaris/classes/sun/nio/ch/EPollPort.java b/src/solaris/classes/sun/nio/ch/EPollPort.java index 6b496ca287a7f8025b061feb7a4603763a565835..17cd171bc8015db6985bf27449adf6d1c6a1b116 100644 --- a/src/solaris/classes/sun/nio/ch/EPollPort.java +++ b/src/solaris/classes/sun/nio/ch/EPollPort.java @@ -318,6 +318,6 @@ final class EPollPort private static native void close0(int fd); static { - Util.load(); + IOUtil.load(); } } diff --git a/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java b/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java index c8bdab4c7be0c73450323be147744554a64f5be1..49f67a8b3dc14e73aee3f2b9f00db16477c2ed4b 100644 --- a/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java +++ b/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java @@ -196,8 +196,4 @@ class EPollSelectorImpl } return this; } - - static { - Util.load(); - } } diff --git a/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java b/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java index 37c1d5b9098032ed0ae1ccfa01ac695d7163b723..145824bf0bc199a5f2d2ea4042bf5cd8824e754f 100644 --- a/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java +++ b/src/solaris/classes/sun/nio/ch/FileDispatcherImpl.java @@ -31,7 +31,7 @@ class FileDispatcherImpl extends FileDispatcher { static { - Util.load(); + IOUtil.load(); init(); } diff --git a/src/solaris/classes/sun/nio/ch/InheritedChannel.java b/src/solaris/classes/sun/nio/ch/InheritedChannel.java index 2917ba9c74abde812c7a3533bf338ef02136763c..ac9b8c5f05b683d90c0291ba1bc1cb5c72d2a7b6 100644 --- a/src/solaris/classes/sun/nio/ch/InheritedChannel.java +++ b/src/solaris/classes/sun/nio/ch/InheritedChannel.java @@ -235,6 +235,6 @@ class InheritedChannel { private static native int peerPort0(int fd); static { - Util.load(); + IOUtil.load(); } } diff --git a/src/solaris/classes/sun/nio/ch/KQueue.java b/src/solaris/classes/sun/nio/ch/KQueue.java index e3466e3d7fe50f5521c2ba7bbd0061d630449af5..f8796c8d47001f274736d523b29285950481f5c8 100644 --- a/src/solaris/classes/sun/nio/ch/KQueue.java +++ b/src/solaris/classes/sun/nio/ch/KQueue.java @@ -115,6 +115,6 @@ class KQueue { throws IOException; static { - Util.load(); + IOUtil.load(); } } diff --git a/src/solaris/classes/sun/nio/ch/KQueuePort.java b/src/solaris/classes/sun/nio/ch/KQueuePort.java index cd16e2e2cca756dcc0993484e39cba81ec2d3b05..c323f076fb2f2da242a63476c4f220e43af84048 100644 --- a/src/solaris/classes/sun/nio/ch/KQueuePort.java +++ b/src/solaris/classes/sun/nio/ch/KQueuePort.java @@ -326,6 +326,6 @@ final class KQueuePort private static native void close0(int fd); static { - Util.load(); + IOUtil.load(); } } diff --git a/src/solaris/classes/sun/nio/ch/NativeThread.java b/src/solaris/classes/sun/nio/ch/NativeThread.java index 7a7e155c4b95f7d9984758884dcd2e914a6b9b30..6e1885e0ec8ba779da9e707b967c0024b10bf406 100644 --- a/src/solaris/classes/sun/nio/ch/NativeThread.java +++ b/src/solaris/classes/sun/nio/ch/NativeThread.java @@ -54,7 +54,7 @@ public class NativeThread { private static native void init(); static { - Util.load(); + IOUtil.load(); init(); } diff --git a/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java b/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java index bf063c70cfd8f165195a16471174bcef1cc37598..3a57bfc4ba2bc5d19378292728d1b831b844adbf 100644 --- a/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java +++ b/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java @@ -126,4 +126,7 @@ public class PollArrayWrapper extends AbstractPollArrayWrapper { private static native void interrupt(int fd); + static { + IOUtil.load(); + } } diff --git a/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java b/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java index d388dd47fd842f4bb46497f80e1acc1f1fe4eeb8..a0645221ed0e65423fc7943912f4ff4c28c12381 100644 --- a/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java @@ -37,7 +37,7 @@ class SinkChannelImpl { // Used to make native read and write calls - private static NativeDispatcher nd; + private static final NativeDispatcher nd = new FileDispatcherImpl(); // The file descriptor associated with this channel FileDescriptor fd; @@ -206,10 +206,4 @@ class SinkChannelImpl throw new IndexOutOfBoundsException(); return write(Util.subsequence(srcs, offset, length)); } - - static { - Util.load(); - nd = new FileDispatcherImpl(); - } - } diff --git a/src/solaris/classes/sun/nio/ch/SolarisEventPort.java b/src/solaris/classes/sun/nio/ch/SolarisEventPort.java index d5a74c10931e74e7d7082d9979b5acfa07e2747e..1ff20373ad58da799b0510e3907cb06f1b972ab7 100644 --- a/src/solaris/classes/sun/nio/ch/SolarisEventPort.java +++ b/src/solaris/classes/sun/nio/ch/SolarisEventPort.java @@ -260,6 +260,6 @@ class SolarisEventPort static { - Util.load(); + IOUtil.load(); } } diff --git a/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java b/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java index cc374127e97b7370f0431fd2c305013ed4cbd834..d632b74259f807c3d0a0adfc650131336c4f6dd3 100644 --- a/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java @@ -37,7 +37,7 @@ class SourceChannelImpl { // Used to make native read and write calls - private static NativeDispatcher nd; + private static final NativeDispatcher nd = new FileDispatcherImpl(); // The file descriptor associated with this channel FileDescriptor fd; @@ -206,10 +206,4 @@ class SourceChannelImpl } } } - - static { - Util.load(); - nd = new FileDispatcherImpl(); - } - } diff --git a/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java b/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java index 3b431e77b01dfb18d53765dcb2cebe8cba1a49da..752b70ee4f000550e6ebf409454918ed22ba0e63 100644 --- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java @@ -345,7 +345,7 @@ class UnixAsynchronousServerSocketChannelImpl throws IOException; static { - Util.load(); + IOUtil.load(); initIDs(); } } diff --git a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java index 8b74488f1acff00b2d96ff9f19d9443bb8f33fdf..c718057f0603c8eb2c5f49da083702afef30f040 100644 --- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java @@ -748,6 +748,6 @@ class UnixAsynchronousSocketChannelImpl private static native void checkConnect(int fdVal) throws IOException; static { - Util.load(); + IOUtil.load(); } } diff --git a/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java index f71345c84c307659399a5f0cd1dbbaa4191a1b0e..73c96cfc22b5f028ed4c71f92da4f32b92435a52 100644 --- a/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/sctp/SctpChannelImpl.java @@ -1106,7 +1106,7 @@ public class SctpChannelImpl extends SctpChannel boolean ready) throws IOException; static { - Util.load(); /* loads nio & net native libraries */ + IOUtil.load(); /* loads nio & net native libraries */ java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Void run() { diff --git a/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java index 84552ba042ddd77c7fe0d88b17068980b18f22a2..424c1d1642de2b0734f85b3afbf7562bfa49765b 100644 --- a/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java @@ -995,7 +995,7 @@ public class SctpMultiChannelImpl extends SctpMultiChannel } static { - Util.load(); /* loads nio & net native libraries */ + IOUtil.load(); /* loads nio & net native libraries */ java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Void run() { diff --git a/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java b/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java index 900d7ab53c0e5894b79a661270991d6685e2f587..d22af25f1d13c7947a44733683a9ed2b6e5b293b 100644 --- a/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java @@ -426,7 +426,7 @@ public class SctpServerChannelImpl extends SctpServerChannel FileDescriptor newfd, InetSocketAddress[] isaa) throws IOException; static { - Util.load(); // loads nio & net native libraries + IOUtil.load(); // loads nio & net native libraries java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Void run() { diff --git a/src/windows/classes/sun/nio/ch/DatagramDispatcher.java b/src/windows/classes/sun/nio/ch/DatagramDispatcher.java index 7cf2f0942938d9bb49cc8dcb264a4f770096f454..fc658b7eb74e98d826d86e2fa7fd4dc76351dad7 100644 --- a/src/windows/classes/sun/nio/ch/DatagramDispatcher.java +++ b/src/windows/classes/sun/nio/ch/DatagramDispatcher.java @@ -36,7 +36,7 @@ import java.net.*; class DatagramDispatcher extends NativeDispatcher { static { - Util.load(); + IOUtil.load(); } int read(FileDescriptor fd, long address, int len) throws IOException { diff --git a/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java b/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java index de3c4f9f705e98ad52668bdc5a1f5289f1542a42..d7126d5c1ae7b32fece098ba8c5cdc3a33b01a65 100644 --- a/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java +++ b/src/windows/classes/sun/nio/ch/FileDispatcherImpl.java @@ -32,7 +32,7 @@ import sun.misc.JavaIOFileDescriptorAccess; class FileDispatcherImpl extends FileDispatcher { static { - Util.load(); + IOUtil.load(); } /** diff --git a/src/windows/classes/sun/nio/ch/FileKey.java b/src/windows/classes/sun/nio/ch/FileKey.java index 397ea49931641dbabd50fb8350b4e10e52764c41..830cc72a5b5df057f0fd8be02568d882ca0e9a68 100644 --- a/src/windows/classes/sun/nio/ch/FileKey.java +++ b/src/windows/classes/sun/nio/ch/FileKey.java @@ -73,6 +73,7 @@ public class FileKey { private static native void initIDs(); static { + IOUtil.load(); initIDs(); } } diff --git a/src/windows/classes/sun/nio/ch/Iocp.java b/src/windows/classes/sun/nio/ch/Iocp.java index f0b83a1a456f22287af96d0f806117868752d9fd..466a08e7ec83da233cc748f8fdd74a9159a4fbdc 100644 --- a/src/windows/classes/sun/nio/ch/Iocp.java +++ b/src/windows/classes/sun/nio/ch/Iocp.java @@ -443,7 +443,7 @@ class Iocp extends AsynchronousChannelGroupImpl { private static native String getErrorMessage(int error); static { - Util.load(); + IOUtil.load(); initIDs(); // thread agnostic I/O on Vista/2008 or newer diff --git a/src/windows/classes/sun/nio/ch/PipeImpl.java b/src/windows/classes/sun/nio/ch/PipeImpl.java index 6eb7dce7efd1ae130057915db46e2efdbce69f7d..4a73c610a5fc1288c9643b20f2f830b99a71c4bd 100644 --- a/src/windows/classes/sun/nio/ch/PipeImpl.java +++ b/src/windows/classes/sun/nio/ch/PipeImpl.java @@ -56,7 +56,6 @@ class PipeImpl private static final Random rnd; static { - Util.load(); byte[] someBytes = new byte[8]; boolean resultOK = IOUtil.randomBytes(someBytes); if (resultOK) { diff --git a/src/windows/classes/sun/nio/ch/SocketDispatcher.java b/src/windows/classes/sun/nio/ch/SocketDispatcher.java index a03d0af93ad30e9f259f25e1b9af4cc950fc18e7..82cfcd56480c93476492fadb3af1b5a8bfd765da 100644 --- a/src/windows/classes/sun/nio/ch/SocketDispatcher.java +++ b/src/windows/classes/sun/nio/ch/SocketDispatcher.java @@ -36,7 +36,7 @@ class SocketDispatcher extends NativeDispatcher { static { - Util.load(); + IOUtil.load(); } int read(FileDescriptor fd, long address, int len) throws IOException { diff --git a/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java b/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java index b85271e686e13cec469d09b3b474e341670014b5..fd3fa538c13a5f8ff1889357fe4365898c41f150 100644 --- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java +++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java @@ -750,6 +750,6 @@ public class WindowsAsynchronousFileChannelImpl private static native void close0(long handle); static { - Util.load(); + IOUtil.load(); } } diff --git a/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java b/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java index 00d6c4631761b237e496ffd2d0707ba256602088..9a25da92bea55d60f410d70114e3501b28b40b11 100644 --- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java +++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousServerSocketChannelImpl.java @@ -363,7 +363,7 @@ class WindowsAsynchronousServerSocketChannelImpl private static native void closesocket0(long socket) throws IOException; static { - Util.load(); + IOUtil.load(); initIDs(); } } diff --git a/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java b/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java index b76b682877436bee1c7c4ad44d0093a0859056a9..124205a65f7948f0b29b1f40720281ac6406a080 100644 --- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java +++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java @@ -919,7 +919,7 @@ class WindowsAsynchronousSocketChannelImpl private static native void closesocket0(long socket) throws IOException; static { - Util.load(); + IOUtil.load(); initIDs(); } } diff --git a/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java b/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java index 1034bb7d82f96a3ce19c957da598f3c052cdd470..bcaaecd9a26569d7ceb2b27a44f10e79ba992e96 100644 --- a/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java +++ b/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java @@ -611,6 +611,6 @@ final class WindowsSelectorImpl extends SelectorImpl { } static { - Util.load(); + IOUtil.load(); } } diff --git a/test/ProblemList.txt b/test/ProblemList.txt index 00a354a7b0d4f7f99788942d6e2ebf961125183c..1f594fe3d3bc9b22de881407fc5b754140af441a 100644 --- a/test/ProblemList.txt +++ b/test/ProblemList.txt @@ -208,7 +208,7 @@ sun/net/www/http/HttpClient/ProxyTest.java generic-all # jdk_io # 7160013 -java/io/File/MaxPathLength.java windows-all +#java/io/File/MaxPathLength.java windows-all ############################################################################ @@ -336,12 +336,6 @@ com/sun/jdi/SuspendThreadTest.java generic-all # Filed 6653793 com/sun/jdi/RedefineCrossEvent.java generic-all -# Filed 6987312 -com/sun/jdi/DoubleAgentTest.java generic-all - -# Filed 7020857 -com/sun/jdi/FieldWatchpoints.java generic-all - # Filed 6402201 com/sun/jdi/ProcessAttachTest.sh generic-all diff --git a/test/TEST.ROOT b/test/TEST.ROOT index 6bf72964f6619f6c5f71f701ef74b3ead4d3f7b8..0aba9d3bc72b1b7bea1295af385c87ee2e919df2 100644 --- a/test/TEST.ROOT +++ b/test/TEST.ROOT @@ -9,3 +9,6 @@ othervm.dirs=java/awt java/beans java/rmi javax/accessibility javax/imageio java # Tests that cannot run concurrently exclusiveAccess.dirs=java/rmi/Naming java/util/Currency java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi + +# Group definitions +groups=TEST.groups [closed/TEST.groups] diff --git a/test/TEST.groups b/test/TEST.groups new file mode 100644 index 0000000000000000000000000000000000000000..0674bdc1d91039a508f7625286d4f87d749310a4 --- /dev/null +++ b/test/TEST.groups @@ -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 diff --git a/test/java/io/BufferedInputStream/LargeCopyWithMark.java b/test/java/io/BufferedInputStream/LargeCopyWithMark.java new file mode 100644 index 0000000000000000000000000000000000000000..2555a1faa5fa1808b9dea21012cc97c397138626 --- /dev/null +++ b/test/java/io/BufferedInputStream/LargeCopyWithMark.java @@ -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 {} +} diff --git a/test/java/io/File/MaxPathLength.java b/test/java/io/File/MaxPathLength.java index 4111550bbd2be39d62e87c0ef8f7ca143ede7176..7ec379cf1d1917eca4d9af184e77bb06ddc8e26d 100644 --- a/test/java/io/File/MaxPathLength.java +++ b/test/java/io/File/MaxPathLength.java @@ -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 @@ public class MaxPathLength { System.err.println("Warning: Test directory structure exists already!"); return; } - boolean couldMakeTestDirectory = dirFile.mkdirs(); - if (!couldMakeTestDirectory) { - throw new RuntimeException ("Could not create test directory structure"); - } + Files.createDirectories(dirFile.toPath()); + try { if (tryAbsolute) dirFile = new File(dirFile.getCanonicalPath()); diff --git a/test/java/io/pathNames/General.java b/test/java/io/pathNames/General.java index a156be92be06af921c49fc6d18916d0a1ff9a6bb..29be50e298b3a46364eedfc24d88c4b47fffc78a 100644 --- a/test/java/io/pathNames/General.java +++ b/test/java/io/pathNames/General.java @@ -28,6 +28,7 @@ import java.io.*; import java.util.*; +import java.nio.file.*; public class General { @@ -57,7 +58,7 @@ public class General { for (int i = 0; i < dl.length; i++) { File f = new File(subdir, dl[i]); File df = new File(dir, f.getPath()); - if (df.exists() && df.isFile()) { + if (Files.isRegularFile(df.toPath(), LinkOption.NOFOLLOW_LINKS)) { return f.getPath(); } } @@ -65,7 +66,7 @@ public class General { File f = (subdir.length() == 0) ? new File(dl[i]) : new File(subdir, dl[i]); File df = new File(dir, f.getPath()); - if (df.exists() && df.isDirectory()) { + if (Files.isDirectory(df.toPath(), LinkOption.NOFOLLOW_LINKS)) { String[] dl2 = df.list(); if (dl2 != null) { String ff = findSomeFile(dir, f.getPath(), dl2); @@ -90,7 +91,7 @@ public class General { } for (int i = 0; i < dl.length; i++) { File f = new File(dir, dl[i]); - if (f.isFile()) { + if (Files.isRegularFile(f.toPath(), LinkOption.NOFOLLOW_LINKS)) { return dl[i]; } } @@ -127,7 +128,7 @@ public class General { } for (int i = 0; i < dl.length; i++) { File f = new File(d, dl[i]); - if (f.isDirectory()) { + if (Files.isDirectory(f.toPath(), LinkOption.NOFOLLOW_LINKS)) { String[] dl2 = f.list(); if (dl2 == null || dl2.length >= 250) { /* Heuristic to avoid scanning huge directories */ @@ -314,7 +315,7 @@ public class General { /* Normal name */ if (f.exists()) { - if (f.isDirectory() && f.list() != null) { + if (Files.isDirectory(f.toPath(), LinkOption.NOFOLLOW_LINKS) && f.list() != null) { if ((n = findSomeFile(ans, create)) != null) checkSlashes(d, create, ans + n, ask + n); if ((n = findSomeDir(ans, create)) != null) diff --git a/test/java/lang/SecurityManager/CheckPackageAccess.java b/test/java/lang/SecurityManager/CheckPackageAccess.java index 7167bbb96c8311d06a2bfc9437396b35bdcf1338..c6b9a1e59be7295b10c5bdcae9c3a388a32ff9ce 100644 --- a/test/java/lang/SecurityManager/CheckPackageAccess.java +++ b/test/java/lang/SecurityManager/CheckPackageAccess.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6741606 7146431 8000450 + * @bug 6741606 7146431 8000450 8019830 * @summary Make sure all restricted packages listed in the package.access * property in the java.security file are blocked * @run main/othervm CheckPackageAccess @@ -54,6 +54,7 @@ public class CheckPackageAccess { "com.sun.imageio.", "com.sun.istack.internal.", "com.sun.jmx.", + "com.sun.media.sound.", "com.sun.proxy.", "com.sun.org.apache.bcel.internal.", "com.sun.org.apache.regexp.internal.", diff --git a/test/java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java b/test/java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java index 65d171adf4313f4fd8d95e98a5073046ffce8faf..f60c33525a87180d1a62c96719e4239602bd504b 100644 --- a/test/java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java +++ b/test/java/lang/annotation/AnnotationType/AnnotationTypeDeadlockTest.java @@ -28,6 +28,9 @@ */ import java.lang.annotation.Retention; +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; @@ -66,17 +69,6 @@ public class AnnotationTypeDeadlockTest { } } - static void dumpState(Task task) { - System.err.println( - "Task[" + task.getName() + "].state: " + - task.getState() + " ..." - ); - for (StackTraceElement ste : task.getStackTrace()) { - System.err.println("\tat " + ste); - } - System.err.println(); - } - public static void main(String[] args) throws Exception { CountDownLatch prepareLatch = new CountDownLatch(2); AtomicInteger goLatch = new AtomicInteger(1); @@ -88,18 +80,22 @@ public class AnnotationTypeDeadlockTest { prepareLatch.await(); // let them go goLatch.set(0); - // attempt to join them - taskA.join(5000L); - taskB.join(5000L); - - if (taskA.isAlive() || taskB.isAlive()) { - dumpState(taskA); - dumpState(taskB); - throw new IllegalStateException( - taskA.getState() == Thread.State.BLOCKED && - taskB.getState() == Thread.State.BLOCKED - ? "deadlock detected" - : "unexpected condition"); + // obtain ThreadMXBean + ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); + // wait for threads to finish or dead-lock + while (taskA.isAlive() || taskB.isAlive()) { + // attempt to join threads + taskA.join(500L); + taskB.join(500L); + // detect dead-lock + long[] deadlockedIds = threadBean.findMonitorDeadlockedThreads(); + if (deadlockedIds != null && deadlockedIds.length > 0) { + StringBuilder sb = new StringBuilder("deadlock detected:\n\n"); + for (ThreadInfo ti : threadBean.getThreadInfo(deadlockedIds, Integer.MAX_VALUE)) { + sb.append(ti); + } + throw new IllegalStateException(sb.toString()); + } } } } diff --git a/test/java/lang/annotation/TypeAnnotationReflection.java b/test/java/lang/annotation/TypeAnnotationReflection.java index 6b4d167ef8069571a1b88fbda42435f3b80cf544..2c7da746a7f65428c2e0221940bf2fadc484adad 100644 --- a/test/java/lang/annotation/TypeAnnotationReflection.java +++ b/test/java/lang/annotation/TypeAnnotationReflection.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8004698 8007073 + * @bug 8004698 8007073 8022343 * @summary Unit test for type annotations */ @@ -58,7 +58,7 @@ public class TypeAnnotationReflection { } private static void testSuper() throws Exception { - check(Object.class.getAnnotatedSuperclass().getAnnotations().length == 0); + check(Object.class.getAnnotatedSuperclass() == null); check(Class.class.getAnnotatedSuperclass().getAnnotations().length == 0); AnnotatedType a; diff --git a/test/java/lang/annotation/typeAnnotations/GetAnnotatedSuperclass.java b/test/java/lang/annotation/typeAnnotations/GetAnnotatedSuperclass.java new file mode 100644 index 0000000000000000000000000000000000000000..d112203a90f2636f9af669049399ea08e9125ff7 --- /dev/null +++ b/test/java/lang/annotation/typeAnnotations/GetAnnotatedSuperclass.java @@ -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 {} +} diff --git a/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java b/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java index 9e37d6670f45e501dd5b5b82e1e55b535a047ade..1cc530e6541f4a8906cc91780f90bbf40c8e07d8 100644 --- a/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java +++ b/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java @@ -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.*; diff --git a/test/java/math/BigDecimal/IntegralDivisionTests.java b/test/java/math/BigDecimal/IntegralDivisionTests.java index 1e28e1d7543a315e06538749720759807e0f63c7..ab6b624c98b7fe195dc5f5a4471a1a15671f5ebd 100644 --- a/test/java/math/BigDecimal/IntegralDivisionTests.java +++ b/test/java/math/BigDecimal/IntegralDivisionTests.java @@ -22,7 +22,7 @@ */ /* * @test - * @bug 4904082 4917089 6337226 + * @bug 4904082 4917089 6337226 6378503 * @summary Tests that integral division and related methods return the proper result and scale. * @author Joseph D. Darcy */ @@ -47,6 +47,9 @@ public class IntegralDivisionTests { {new BigDecimal("400e1"), new BigDecimal("5"), new BigDecimal("80e1")}, {new BigDecimal("400e1"), new BigDecimal("4.999999999"), new BigDecimal("8e2")}, {new BigDecimal("40e2"), new BigDecimal("5"), new BigDecimal("8e2")}, + {BigDecimal.valueOf(1, Integer.MIN_VALUE), + BigDecimal.valueOf(1, -(Integer.MAX_VALUE & 0x7fffff00)), + BigDecimal.valueOf(1, -256)}, }; for(BigDecimal [] testCase: moreTestCases) { diff --git a/test/java/nio/file/WatchService/SensitivityModifier.java b/test/java/nio/file/WatchService/SensitivityModifier.java index 6f9a14cfd60f9ea4fca98eb03116825faa37dc49..08722048b63b0727f0816481fd58df22f2c55060 100644 --- a/test/java/nio/file/WatchService/SensitivityModifier.java +++ b/test/java/nio/file/WatchService/SensitivityModifier.java @@ -54,60 +54,66 @@ public class SensitivityModifier { @SuppressWarnings("unchecked") static void doTest(Path top) throws Exception { FileSystem fs = top.getFileSystem(); - WatchService watcher = fs.newWatchService(); + try (WatchService watcher = fs.newWatchService()) { - // create directories and files - int nDirs = 5 + rand.nextInt(20); - int nFiles = 50 + rand.nextInt(50); - Path[] dirs = new Path[nDirs]; - Path[] files = new Path[nFiles]; - for (int i=0; i event = key.pollEvents().iterator().next(); - if (event.kind() != ENTRY_MODIFY) - throw new RuntimeException("Unexpected event: " + event); - Path name = ((WatchEvent)event).context(); - if (!name.equals(file.getFileName())) - throw new RuntimeException("Unexpected context: " + name); - System.out.println("Event OK"); + 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)event).context(); + if (name.equals(file.getFileName())) { + eventReceived = true; + break; + } + } + key.reset(); + key = watcher.poll(1, TimeUnit.SECONDS); + } while (key != null && !eventReceived); - // drain events (to avoid interference) - do { - key.pollEvents(); - key.reset(); - key = watcher.poll(1, TimeUnit.SECONDS); - } while (key != null); + // 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); + // re-register the directories to force changing their sensitivity + // level + register(dirs, watcher); + } } - - // done - watcher.close(); } public static void main(String[] args) throws Exception { diff --git a/test/java/util/Arrays/TimSortStackSize.java b/test/java/util/Arrays/TimSortStackSize.java new file mode 100644 index 0000000000000000000000000000000000000000..c05cc52a1634c2e9262b7b6ecb4c9241cf333704 --- /dev/null +++ b/test/java/util/Arrays/TimSortStackSize.java @@ -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 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 chunks = new ArrayDeque(); + 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; + } + +} diff --git a/test/java/util/Collections/Wrappers.java b/test/java/util/Collections/Wrappers.java new file mode 100644 index 0000000000000000000000000000000000000000..3882a4efdd1ad3c49ca87bb194bcac45567905e8 --- /dev/null +++ b/test/java/util/Collections/Wrappers.java @@ -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 cases = new ArrayList<>(); + LinkedList seedList = new LinkedList<>(); + ArrayList seedRandomAccess = new ArrayList<>(); + TreeSet seedSet = new TreeSet<>(); + TreeMap 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 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()); + } + } +} + diff --git a/test/java/util/Comparator/BasicTest.java b/test/java/util/Comparator/BasicTest.java index 5bbb700e0b38f18ed322ec45ab7252fd47e1211d..b4eb5d4ac40a4ec75999e76579e4b25907855c7b 100644 --- a/test/java/util/Comparator/BasicTest.java +++ b/test/java/util/Comparator/BasicTest.java @@ -90,7 +90,7 @@ public class BasicTest { Thing[] things = new Thing[intValues.length]; for (int i=0; i comp = Comparator.comparing(new ToIntFunction() { + Comparator comp = Comparator.comparingInt(new ToIntFunction() { @Override public int applyAsInt(Thing thing) { return thing.getIntField(); @@ -104,7 +104,7 @@ public class BasicTest { Thing[] things = new Thing[longValues.length]; for (int i=0; i comp = Comparator.comparing(new ToLongFunction() { + Comparator comp = Comparator.comparingLong(new ToLongFunction() { @Override public long applyAsLong(Thing thing) { return thing.getLongField(); @@ -118,7 +118,7 @@ public class BasicTest { Thing[] things = new Thing[doubleValues.length]; for (int i=0; i comp = Comparator.comparing(new ToDoubleFunction() { + Comparator comp = Comparator.comparingDouble(new ToDoubleFunction() { @Override public double applyAsDouble(Thing thing) { return thing.getDoubleField(); @@ -211,8 +211,8 @@ public class BasicTest { }; public void testComparatorDefaultMethods() { - Comparator cmp = Comparator.comparing((Function) People::getFirstName); - Comparator cmp2 = Comparator.comparing((Function) People::getLastName); + Comparator cmp = Comparator.comparing(People::getFirstName); + Comparator cmp2 = Comparator.comparing(People::getLastName); // reverseOrder assertComparison(cmp.reversed(), people[1], people[0]); // thenComparing(Comparator) @@ -222,20 +222,20 @@ public class BasicTest { assertComparison(cmp.thenComparing(People::getLastName), people[0], people[1]); assertComparison(cmp.thenComparing(People::getLastName), people[4], people[0]); // thenComparing(ToIntFunction) - assertComparison(cmp.thenComparing(People::getAge), people[0], people[1]); - assertComparison(cmp.thenComparing(People::getAge), people[1], people[5]); + assertComparison(cmp.thenComparingInt(People::getAge), people[0], people[1]); + assertComparison(cmp.thenComparingInt(People::getAge), people[1], people[5]); // thenComparing(ToLongFunction) - assertComparison(cmp.thenComparing(People::getAgeAsLong), people[0], people[1]); - assertComparison(cmp.thenComparing(People::getAgeAsLong), people[1], people[5]); + assertComparison(cmp.thenComparingLong(People::getAgeAsLong), people[0], people[1]); + assertComparison(cmp.thenComparingLong(People::getAgeAsLong), people[1], people[5]); // thenComparing(ToDoubleFunction) - assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[0], people[1]); - assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[1], people[5]); + assertComparison(cmp.thenComparingDouble(People::getAgeAsDouble), people[0], people[1]); + assertComparison(cmp.thenComparingDouble(People::getAgeAsDouble), people[1], people[5]); } public void testNullsFirst() { Comparator strcmp = Comparator.nullsFirst(Comparator.naturalOrder()); - Comparator cmp = Comparator.comparing(People::getLastName, strcmp) + Comparator cmp = Comparator.comparing(People::getLastName, strcmp) .thenComparing(People::getFirstName, strcmp); // Mary.null vs Mary.Cook - solve by last name assertComparison(cmp, people[6], people[5]); @@ -243,7 +243,7 @@ public class BasicTest { assertComparison(cmp, people[7], people[6]); // More than one thenComparing - strcmp = Comparator.nullsFirst(Comparator.comparing((ToIntFunction) String::length) + strcmp = Comparator.nullsFirst(Comparator.comparingInt(String::length) .thenComparing(String.CASE_INSENSITIVE_ORDER)); assertComparison(strcmp, null, "abc"); assertComparison(strcmp, "ab", "abc"); @@ -273,7 +273,7 @@ public class BasicTest { public void testNullsLast() { Comparator strcmp = Comparator.nullsLast(Comparator.naturalOrder()); - Comparator cmp = Comparator.comparing(People::getLastName, strcmp) + Comparator cmp = Comparator.comparing(People::getLastName, strcmp) .thenComparing(People::getFirstName, strcmp); // Mary.null vs Mary.Cook - solve by last name assertComparison(cmp, people[5], people[6]); @@ -281,7 +281,7 @@ public class BasicTest { assertComparison(cmp, people[7], people[6]); // More than one thenComparing - strcmp = Comparator.nullsLast(Comparator.comparing((ToIntFunction) String::length) + strcmp = Comparator.nullsLast(Comparator.comparingInt(String::length) .thenComparing(String.CASE_INSENSITIVE_ORDER)); assertComparison(strcmp, "abc", null); assertComparison(strcmp, "ab", "abc"); @@ -341,28 +341,28 @@ public class BasicTest { } catch (NullPointerException npe) {} try { - Comparator cmp = Comparator.comparing((Function) null, Comparator.naturalOrder()); + Comparator cmp = Comparator.comparing(null, Comparator.naturalOrder()); fail("comparing(null, cmp) should throw NPE"); } catch (NullPointerException npe) {} try { - Comparator cmp = Comparator.comparing((Function) People::getFirstName, null); + Comparator cmp = Comparator.comparing(People::getFirstName, null); fail("comparing(f, null) should throw NPE"); } catch (NullPointerException npe) {} try { - Comparator cmp = Comparator.comparing((Function) null); + Comparator cmp = Comparator.comparing(null); fail("comparing(null) should throw NPE"); } catch (NullPointerException npe) {} try { - Comparator cmp = Comparator.comparing((ToIntFunction) null); + Comparator cmp = Comparator.comparingInt(null); fail("comparing(null) should throw NPE"); } catch (NullPointerException npe) {} try { - Comparator cmp = Comparator.comparing((ToLongFunction) null); + Comparator cmp = Comparator.comparingLong(null); fail("comparing(null) should throw NPE"); } catch (NullPointerException npe) {} try { - Comparator cmp = Comparator.comparing((ToDoubleFunction) null); + Comparator cmp = Comparator.comparingDouble(null); fail("comparing(null) should throw NPE"); } catch (NullPointerException npe) {} } diff --git a/test/java/util/Map/EntryComparators.java b/test/java/util/Map/EntryComparators.java index ce607a3690128e3e9a3e6dc39049817fb06b0688..631107eada906f5c7872e8838a848ebd4fc42871 100644 --- a/test/java/util/Map/EntryComparators.java +++ b/test/java/util/Map/EntryComparators.java @@ -115,8 +115,8 @@ public class EntryComparators { // Comparator 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 cmp1 = Comparator.comparing((Function) People::getFirstName); - Comparator cmp2 = Comparator.comparing((Function) People::getLastName); + Comparator cmp1 = Comparator.comparing(People::getFirstName); + Comparator cmp2 = Comparator.comparing(People::getLastName); Comparator cmp = cmp1.thenComparing(cmp2); assertPairComparison(people[0], people[0], people[1], people[1], diff --git a/test/java/util/Random/RandomStreamTest.java b/test/java/util/Random/RandomStreamTest.java index f7b799c484a2762bd04a4b61ccb87c72b093129a..e96d57e2639a32ca60073c93c02484b70e17d498 100644 --- a/test/java/util/Random/RandomStreamTest.java +++ b/test/java/util/Random/RandomStreamTest.java @@ -82,13 +82,6 @@ public class RandomStreamTest { assertEquals(destination.size(), count); } - @Test(dataProvider = "suppliers") - public void testRandomGaussianStream(final Random random, final int count) { - final List destination = new ArrayList<>(count); - random.gaussians().limit(count).forEach(destination::add); - assertEquals(destination.size(), count); - } - @Test public void testIntStream() { final long seed = System.currentTimeMillis(); @@ -131,20 +124,6 @@ public class RandomStreamTest { assertEquals(a, b); } - @Test - public void testGaussianStream() { - final long seed = System.currentTimeMillis(); - final Random r1 = new Random(seed); - final double[] a = new double[SIZE]; - for (int i=0; i < SIZE; i++) { - a[i] = r1.nextGaussian(); - } - - final Random r2 = new Random(seed); // same seed - final double[] b = r2.gaussians().limit(SIZE).toArray(); - assertEquals(a, b); - } - @Test public void testThreadLocalIntStream() throws InterruptedException, ExecutionException, TimeoutException { ThreadLocalRandom tlr = ThreadLocalRandom.current(); @@ -163,12 +142,6 @@ public class RandomStreamTest { testRandomResultSupplierConcurrently(() -> tlr.doubles().limit(SIZE).boxed().collect(toList())); } - @Test - public void testThreadLocalGaussianStream() throws InterruptedException, ExecutionException, TimeoutException { - ThreadLocalRandom tlr = ThreadLocalRandom.current(); - testRandomResultSupplierConcurrently(() -> tlr.gaussians().limit(SIZE).boxed().collect(toList())); - } - void testRandomResultSupplierConcurrently(Supplier s) throws InterruptedException, ExecutionException, TimeoutException { // Produce 10 completable future tasks final int tasks = 10; diff --git a/test/java/util/Random/RandomTest.java b/test/java/util/Random/RandomTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e56ffde1961a34bf540438d145cccae17c335e75 --- /dev/null +++ b/test/java/util/Random/RandomTest.java @@ -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 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 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); + } + +} diff --git a/test/java/util/SplittableRandom/SplittableRandomTest.java b/test/java/util/SplittableRandom/SplittableRandomTest.java new file mode 100644 index 0000000000000000000000000000000000000000..57e1a3434a366e75b933011851ee9372e6674d09 --- /dev/null +++ b/test/java/util/SplittableRandom/SplittableRandomTest.java @@ -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 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 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); + } + +} diff --git a/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java b/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e4e91f597bb57b3364f3721533314a43a43ed309 --- /dev/null +++ b/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java @@ -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 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 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); + } + +} diff --git a/test/java/util/concurrent/locks/StampedLock/ReadersUnlockAfterWriteUnlock.java b/test/java/util/concurrent/locks/StampedLock/ReadersUnlockAfterWriteUnlock.java new file mode 100644 index 0000000000000000000000000000000000000000..6d459372515fd270835864e0684a3952b5b6ae20 --- /dev/null +++ b/test/java/util/concurrent/locks/StampedLock/ReadersUnlockAfterWriteUnlock.java @@ -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; + } + +} diff --git a/test/java/util/function/BinaryOperator/BasicTest.java b/test/java/util/function/BinaryOperator/BasicTest.java index 1519fb88177dca7719ba60e371eeef80e24d5a23..0c37a9c5c620089cee5f7b374b90bda1aa0ab455 100644 --- a/test/java/util/function/BinaryOperator/BasicTest.java +++ b/test/java/util/function/BinaryOperator/BasicTest.java @@ -67,26 +67,26 @@ public class BasicTest { }; public void testMaxBy() { - Comparator cmp = Comparator.comparing((Function) People::getFirstName); + Comparator cmp = Comparator.comparing(People::getFirstName); // lesser assertSame(maxBy(cmp).apply(people[0], people[1]), people[1]); // euqal - cmp = Comparator.comparing((Function) People::getLastName); + cmp = Comparator.comparing(People::getLastName); assertSame(maxBy(cmp).apply(people[0], people[1]), people[0]); // greater - cmp = Comparator.comparing((ToIntFunction) People::getAge); + cmp = Comparator.comparingInt(People::getAge); assertSame(maxBy(cmp).apply(people[0], people[1]), people[0]); } - public void testLesserOf() { - Comparator cmp = Comparator.comparing((Function) People::getFirstName); + public void testMinBy() { + Comparator cmp = Comparator.comparing(People::getFirstName); // lesser assertSame(minBy(cmp).apply(people[0], people[1]), people[0]); // euqal - cmp = Comparator.comparing((Function) People::getLastName); + cmp = Comparator.comparing(People::getLastName); assertSame(minBy(cmp).apply(people[0], people[1]), people[0]); // greater - cmp = Comparator.comparing((ToIntFunction) People::getAge); + cmp = Comparator.comparingInt(People::getAge); assertSame(minBy(cmp).apply(people[0], people[1]), people[1]); } diff --git a/test/java/util/logging/Logger/getLogger/TestLogger.java b/test/java/util/logging/Logger/getLogger/TestLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..cf6abc449dd81bb3172635e0eedc052565cd0ec2 --- /dev/null +++ b/test/java/util/logging/Logger/getLogger/TestLogger.java @@ -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 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)); + } +} diff --git a/src/share/classes/sun/misc/Compare.java b/test/java/util/logging/Logger/getLogger/testlogger/MyResource.java similarity index 53% rename from src/share/classes/sun/misc/Compare.java rename to test/java/util/logging/Logger/getLogger/testlogger/MyResource.java index 400fc1713ca2c4808f3fac842ef7b212da338097..84b0cd258cb776058cb431713ac9cb579ecac586 100644 --- a/src/share/classes/sun/misc/Compare.java +++ b/test/java/util/logging/Logger/getLogger/testlogger/MyResource.java @@ -1,12 +1,10 @@ /* - * Copyright (c) 1996, 1997, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. + * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or @@ -22,25 +20,33 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package testlogger; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Properties; +import java.util.ResourceBundle; /** - * Compare: an interface to enable users to define the result of - * a comparison of two objects. - * - * @author Sunita Mani + * A dummy resource bundle for testing purposes. + * @author danielfuchs */ +public class MyResource extends ResourceBundle { + Map bundle = new HashMap<>(); -package sun.misc; - -public interface Compare { + @Override + protected Object handleGetObject(String key) { + bundle.put(key,"Localized: " + key); + return bundle.get(key); + } - /** - * doCompare - * - * @param obj1 first object to compare. - * @param obj2 second object to compare. - * @return -1 if obj1 < obj2, 0 if obj1 == obj2, 1 if obj1 > obj2. - */ - public int doCompare(Object obj1, Object obj2); + @Override + public Enumeration getKeys() { + final Hashtable h = new Hashtable<>(bundle); + return h.keys(); + } } diff --git a/test/java/util/regex/PatternTest.java b/test/java/util/regex/PatternTest.java new file mode 100644 index 0000000000000000000000000000000000000000..aab17319ae41288fb6453461a4fe79592216a6ab --- /dev/null +++ b/test/java/util/regex/PatternTest.java @@ -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") + public static Object[][] makeStreamTestData() { + List data = new ArrayList<>(); + + String description = ""; + String input = "awgqwefg1fefw4vssv1vvv1"; + Pattern pattern = Pattern.compile("4"); + List 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 + 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") + public void testStrings(String description, String input, Pattern pattern, List expected) { + Supplier> ss = () -> pattern.splitAsStream(input); + withData(TestData.Factory.ofSupplier(description, ss)) + .stream(LambdaTestHelpers.identity()) + .expectedResult(expected) + .exercise(); + } +} diff --git a/test/java/util/regex/RegExTest.java b/test/java/util/regex/RegExTest.java index f0563d94e2e7ea8029a83867b0fb14dcf304c796..aba74b0c479f7a4f1a0d3043ef8b2d06e28d07a7 100644 --- a/test/java/util/regex/RegExTest.java +++ b/test/java/util/regex/RegExTest.java @@ -33,7 +33,7 @@ * 5013885 5003322 4988891 5098443 5110268 6173522 4829857 5027748 6376940 * 6358731 6178785 6284152 6231989 6497148 6486934 6233084 6504326 6635133 * 6350801 6676425 6878475 6919132 6931676 6948903 6990617 7014645 7039066 - * 7067045 7014640 7189363 8007395 8013252 8013254 8012646 + * 7067045 7014640 7189363 8007395 8013252 8013254 8012646 8023647 */ import java.util.regex.*; @@ -146,6 +146,7 @@ public class RegExTest { linebreakTest(); branchTest(); groupCurlyNotFoundSuppTest(); + groupCurlyBackoffTest(); patternAsPredicate(); if (failure) { throw new @@ -3999,6 +4000,15 @@ public class RegExTest { report("GroupCurly NotFoundSupp"); } + // This test is for 8023647 + private static void groupCurlyBackoffTest() throws Exception { + if (!"abc1c".matches("(\\w)+1\\1") || + "abc11".matches("(\\w)+1\\1")) { + failCount++; + } + report("GroupCurly backoff"); + } + // This test is for 8012646 private static void patternAsPredicate() throws Exception { Predicate p = Pattern.compile("[a-z]+").asPredicate(); diff --git a/test/java/util/stream/test/org/openjdk/tests/java/util/SplittableRandomTest.java b/test/java/util/stream/test/org/openjdk/tests/java/util/SplittableRandomTest.java new file mode 100644 index 0000000000000000000000000000000000000000..30b5e7d6da8fc28bb1be7998422fcac1bfc11618 --- /dev/null +++ b/test/java/util/stream/test/org/openjdk/tests/java/util/SplittableRandomTest.java @@ -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 implements Spliterator { + final SplittableRandom rng; + long index; + final long fence; + final Function rngF; + + RandomBoxedSpliterator(SplittableRandom rng, long index, long fence, Function rngF) { + this.rng = rng; + this.index = index; + this.fence = fence; + this.rngF = rngF; + } + + public RandomBoxedSpliterator 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 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 > ResultAsserter> randomAsserter(int size, T origin, T bound) { + return (act, exp, ord, par) -> { + int count = 0; + Set> values = new HashSet<>(); + for (Comparable 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 data = new ArrayList<>(); + + // Function to create a stream using a RandomBoxedSpliterator + + Function, 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> 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 data = new ArrayList<>(); + + // Function to create a stream using a RandomBoxedSpliterator + + Function, 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> 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 data = new ArrayList<>(); + + // Function to create a stream using a RandomBoxedSpliterator + + Function, 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> ra) { + withData(data). + stream(s -> s). + without(DoubleStreamTestScenario.PAR_STREAM_TO_ARRAY_CLEAR_SIZED). + resultAsserter(ra). + exercise(); + } +} diff --git a/test/java/util/zip/TestExtraTime.java b/test/java/util/zip/TestExtraTime.java index 9923ea693e0698ff28e8918b90f37b635e97bd11..b96c85f7c02fcdb5f483b28ad2fba58b45049cfc 100644 --- a/test/java/util/zip/TestExtraTime.java +++ b/test/java/util/zip/TestExtraTime.java @@ -23,7 +23,7 @@ /** * @test - * @bug 4759491 6303183 7012868 8015666 + * @bug 4759491 6303183 7012868 8015666 8023713 * @summary Test ZOS and ZIS timestamp in extra field correctly */ @@ -32,6 +32,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.FileTime; +import java.util.Arrays; import java.util.TimeZone; import java.util.concurrent.TimeUnit; import java.util.zip.ZipEntry; @@ -52,24 +53,26 @@ public class TestExtraTime { FileTime ctime = FileTime.from(time - 300000, TimeUnit.MILLISECONDS); TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai"); - test(mtime, null, null, null); - // 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 @@ public class TestExtraTime { } ByteArrayOutputStream baos = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(baos); - ZipEntry ze = new ZipEntry("TestExtreTime.java"); - + ZipEntry ze = new ZipEntry("TestExtraTime.java"); + ze.setExtra(extra); ze.setLastModifiedTime(mtime); if (atime != null) ze.setLastAccessTime(atime); @@ -87,6 +90,14 @@ public class TestExtraTime { ze.setCreationTime(ctime); zos.putNextEntry(ze); zos.write(new byte[] { 1,2 ,3, 4}); + + // append an extra entry to help check if the length and data + // of the extra field are being correctly written (in previous + // entry). + if (extra != null) { + ze = new ZipEntry("TestExtraEntry"); + zos.putNextEntry(ze); + } zos.close(); if (tz != null) { TimeZone.setDefault(tz0); @@ -96,23 +107,23 @@ public class TestExtraTime { new ByteArrayInputStream(baos.toByteArray())); ze = zis.getNextEntry(); zis.close(); - check(mtime, atime, ctime, ze); + check(mtime, atime, ctime, ze, extra); // ZipFile Path zpath = Paths.get(System.getProperty("test.dir", "."), - "TestExtraTimp.zip"); + "TestExtraTime.zip"); Files.copy(new ByteArrayInputStream(baos.toByteArray()), zpath); ZipFile zf = new ZipFile(zpath.toFile()); - ze = zf.getEntry("TestExtreTime.java"); + ze = zf.getEntry("TestExtraTime.java"); // ZipFile read entry from cen, which does not have a/ctime, // for now. - check(mtime, null, null, ze); + check(mtime, null, null, ze, extra); zf.close(); Files.delete(zpath); } static void check(FileTime mtime, FileTime atime, FileTime ctime, - ZipEntry ze) { + ZipEntry ze, byte[] extra) { /* System.out.printf(" mtime [%tc]: [%tc]/[%tc]%n", mtime.to(TimeUnit.MILLISECONDS), @@ -130,5 +141,17 @@ public class TestExtraTime { ctime.to(TimeUnit.SECONDS) != ze.getCreationTime().to(TimeUnit.SECONDS)) throw new RuntimeException("Timestamp: storing ctime failed!"); + if (extra != null) { + // if extra data exists, the current implementation put it at + // the end of the extra data array (implementation detail) + byte[] extra1 = ze.getExtra(); + if (extra1 == null || extra1.length < extra.length || + !Arrays.equals(Arrays.copyOfRange(extra1, + extra1.length - extra.length, + extra1.length), + extra)) { + throw new RuntimeException("Timestamp: storing extra field failed!"); + } + } } } diff --git a/test/sun/security/krb5/auto/KPEquals.java b/test/sun/security/krb5/auto/KPEquals.java new file mode 100644 index 0000000000000000000000000000000000000000..7a7aaa34f24a9abaf03b9d9388bd56970936ef87 --- /dev/null +++ b/test/sun/security/krb5/auto/KPEquals.java @@ -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); + } +} diff --git a/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java b/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java index d5fdadd9b1eee66e62457b2f6f06fef1fef88a0e..d4e00855dc6db51c733faef873d93342fc777575 100644 --- a/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java +++ b/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java @@ -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 @@ public class SessionCacheSizeTests { /* * 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 @@ public class SessionCacheSizeTests { * Fork off the other side, then do your work. */ SessionCacheSizeTests() throws Exception { - /* * create the SSLServerSocket and SSLSocket factories */ @@ -323,46 +326,87 @@ public class SessionCacheSizeTests { int serverConns = MAX_ACTIVE_CONNECTIONS / (serverPorts.length); int remainingConns = MAX_ACTIVE_CONNECTIONS % (serverPorts.length); - if (separateServerThread) { - for (int i = 0; i < serverPorts.length; i++) { + 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); + } + } + } catch (Exception e) { + startException = e; + } - // distribute remaining connections among the available ports - if (i < remainingConns) - startServer(serverPorts[i], (serverConns + 1), true); - else - startServer(serverPorts[i], serverConns, true); + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + if (serverThread != null) { + serverThread.join(); } - 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); + if (clientThread != null) { + clientThread.join(); } } /* - * Wait for other side to close down. + * When we get here, the test is pretty much over. */ + Exception local; + Exception remote; + if (separateServerThread) { - serverThread.join(); + remote = serverException; + local = clientException; } else { - clientThread.join(); + remote = clientException; + local = serverException; } + Exception exception = null; + /* - * 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. + * 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 @@ public class SessionCacheSizeTests { }; serverThread.start(); } else { - doServerSide(port, nConns); + try { + doServerSide(port, nConns); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } } } @@ -409,7 +459,11 @@ public class SessionCacheSizeTests { }; clientThread.start(); } else { - doClientSide(); + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } } } } diff --git a/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java b/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java index 3d0946724f546dc4b6df356bd90bf48cf40c5a62..9264cb08723c13f87995d84ef3f406b3ce56037d 100644 --- a/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java +++ b/test/sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java @@ -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 @@ public class SessionTimeOutTests { 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 @@ public class SessionTimeOutTests { int serverConns = MAX_ACTIVE_CONNECTIONS / (serverPorts.length); int remainingConns = MAX_ACTIVE_CONNECTIONS % (serverPorts.length); + Exception startException = null; + try { + if (separateServerThread) { + for (int i = 0; i < serverPorts.length; i++) { + // distribute remaining connections among the + // 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); + } + } + } catch (Exception e) { + startException = e; + } + + /* + * Wait for other side to close down. + */ 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); + if (serverThread != null) { + serverThread.join(); } - 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); + if (clientThread != null) { + clientThread.join(); } } /* - * Wait for other side to close down. + * When we get here, the test is pretty much over. + * Which side threw the error? */ + Exception local; + Exception remote; + if (separateServerThread) { - serverThread.join(); + remote = serverException; + local = clientException; } else { - clientThread.join(); + remote = clientException; + local = serverException; } + Exception exception = null; + /* - * 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. + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. */ - if (serverException != null) - throw serverException; - if (clientException != null) - throw clientException; + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! } void startServer(final int port, final int nConns, @@ -411,7 +454,13 @@ public class SessionTimeOutTests { }; serverThread.start(); } else { - doServerSide(port, nConns); + try { + doServerSide(port, nConns); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = 0; + } } } @@ -433,7 +482,11 @@ public class SessionTimeOutTests { }; clientThread.start(); } else { - doClientSide(); + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } } } } diff --git a/test/sun/security/ssl/templates/SSLSocketTemplate.java b/test/sun/security/ssl/templates/SSLSocketTemplate.java index e8bfe91db060b333fa357bfad94accf56f76272c..af9f40f77c55a1ed51ddcfc929c2cd19b981a295 100644 --- a/test/sun/security/ssl/templates/SSLSocketTemplate.java +++ b/test/sun/security/ssl/templates/SSLSocketTemplate.java @@ -243,7 +243,7 @@ public class SSLSocketTemplate { * output it. */ if (exception != null) { - if (exception != startException) { + if (exception != startException && startException != null) { exception.addSuppressed(startException); } throw exception; diff --git a/test/sun/security/tools/jarsigner/jvindex.sh b/test/sun/security/tools/jarsigner/jvindex.sh new file mode 100644 index 0000000000000000000000000000000000000000..c4435b68121370c4cd47a542558b8665650a17b3 --- /dev/null +++ b/test/sun/security/tools/jarsigner/jvindex.sh @@ -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 + +