From 72f951e112562a5dcc0c06fd745e93e9d48a80b6 Mon Sep 17 00:00:00 2001 From: Alex Henrie Date: Tue, 17 Nov 2015 23:10:30 -0700 Subject: [PATCH 01/20] 8145278: Fix memory leak in splitPathList Reviewed-by: sspitsyn, dsamersoff, dcubed --- .../share/native/libinstrument/InvocationAdapter.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c index 0c57f8b289d..a74b2b725ba 100644 --- a/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c +++ b/jdk/src/java.instrument/share/native/libinstrument/InvocationAdapter.c @@ -518,18 +518,22 @@ static void splitPathList(const char* str, int* pathCount, char*** paths) { int count = 0; char** segments = NULL; + char** new_segments; char* c = (char*) str; while (*c != '\0') { while (*c == ' ') c++; /* skip leading spaces */ if (*c == '\0') { break; } - if (segments == NULL) { - segments = (char**)malloc( sizeof(char**) ); - } else { - segments = (char**)realloc( segments, (count+1)*sizeof(char**) ); + new_segments = (char**)realloc(segments, (count+1)*sizeof(char*)); + if (new_segments == NULL) { + jplis_assert(0); + free(segments); + count = 0; + segments = NULL; + break; } - jplis_assert(segments != (char**)NULL); + segments = new_segments; segments[count++] = c; c = strchr(c, ' '); if (c == NULL) { From 34abb0688722c725998916cf5b61d7660c24e0c4 Mon Sep 17 00:00:00 2001 From: Gil Tene Date: Wed, 30 Mar 2016 17:04:09 +0200 Subject: [PATCH 02/20] 8147844: new method j.l.Thread.onSpinWait() and the corresponding x86 hotspot instrinsic See JEP-285 for details Co-authored-by: Ivan Krylov Reviewed-by: psandoz, alanb, dholmes --- .../share/classes/java/lang/Thread.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/jdk/src/java.base/share/classes/java/lang/Thread.java b/jdk/src/java.base/share/classes/java/lang/Thread.java index eb47a05427d..972815e16c7 100644 --- a/jdk/src/java.base/share/classes/java/lang/Thread.java +++ b/jdk/src/java.base/share/classes/java/lang/Thread.java @@ -340,6 +340,45 @@ class Thread implements Runnable { sleep(millis); } + /** + * Indicates that the caller is momentarily unable to progress, until the + * occurrence of one or more actions on the part of other activities. By + * invoking this method within each iteration of a spin-wait loop construct, + * the calling thread indicates to the runtime that it is busy-waiting. + * The runtime may take action to improve the performance of invoking + * spin-wait loop constructions. + *

+ * @apiNote + * As an example consider a method in a class that spins in a loop until + * some flag is set outside of that method. A call to the {@code onSpinWait} + * method should be placed inside the spin loop. + *

{@code
+     *     class EventHandler {
+     *         volatile boolean eventNotificationNotReceived;
+     *         void waitForEventAndHandleIt() {
+     *             while ( eventNotificationNotReceived ) {
+     *                 java.lang.Thread.onSpinWait();
+     *             }
+     *             readAndProcessEvent();
+     *         }
+     *
+     *         void readAndProcessEvent() {
+     *             // Read event from some source and process it
+     *              . . .
+     *         }
+     *     }
+     * }
+ *

+ * The code above would remain correct even if the {@code onSpinWait} + * method was not called at all. However on some architectures the Java + * Virtual Machine may issue the processor instructions to address such + * code patterns in a more beneficial way. + *

+ * @since 9 + */ + @HotSpotIntrinsicCandidate + public static void onSpinWait() {} + /** * Initializes a Thread with the current AccessControlContext. * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean) From fd6507d3538a451cdeb8b31ea2ea8633d66c466e Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Wed, 20 Apr 2016 09:57:01 +0200 Subject: [PATCH 03/20] 8072921: -Xincgc should be removed from output Reviewed-by: alanb --- .../share/classes/sun/launcher/resources/launcher.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties index 52d621b414d..f678ba37057 100644 --- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties +++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties @@ -99,7 +99,6 @@ java.launcher.X.usage=\ \ -Xdiag show additional diagnostic messages\n\ \ -Xdiag:resolver show resolver diagnostic messages\n\ \ -Xnoclassgc disable class garbage collection\n\ -\ -Xincgc enable incremental garbage collection\n\ \ -Xloggc: log GC status to a file with time stamps\n\ \ -Xbatch disable background compilation\n\ \ -Xms set initial Java heap size\n\ From 3f6fc8998db487dbf80789d6ae78b07d3aed2933 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Wed, 20 Apr 2016 18:01:02 +0300 Subject: [PATCH 04/20] 8152847: JDI use of sun.boot.class.path needs to be updated for Jigsaw Remove references to bootclasspath Reviewed-by: alanb, sspitsyn --- .../share/classes/com/sun/tools/example/debug/tty/Commands.java | 1 - .../classes/com/sun/tools/example/debug/tty/TTYResources.java | 1 - .../com/sun/tools/example/debug/tty/TTYResources_ja.java | 1 - .../com/sun/tools/example/debug/tty/TTYResources_zh_CN.java | 1 - .../share/classes/com/sun/tools/jdi/VirtualMachineImpl.java | 2 +- 5 files changed, 1 insertion(+), 5 deletions(-) diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java index 61823822d0e..11a376e0f22 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/Commands.java @@ -1534,7 +1534,6 @@ class Commands { PathSearchingVirtualMachine vm = (PathSearchingVirtualMachine)Env.vm(); MessageOutput.println("base directory:", vm.baseDirectory()); MessageOutput.println("classpath:", vm.classPath().toString()); - MessageOutput.println("bootclasspath:", vm.bootClassPath().toString()); } else { MessageOutput.println("The VM does not use paths"); } diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java index c412743c4b6..39e703d88b8 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources.java @@ -74,7 +74,6 @@ public class TTYResources extends java.util.ListResourceBundle { {"Array element is not a method", "Array element is not a method"}, {"Array index must be a integer type", "Array index must be a integer type"}, {"base directory:", "base directory: {0}"}, - {"bootclasspath:", "bootclasspath: {0}"}, {"Breakpoint hit:", "Breakpoint hit: "}, {"breakpoint", "breakpoint {0}"}, {"Breakpoints set:", "Breakpoints set:"}, diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_ja.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_ja.java index 1cb6d231d50..b3562226398 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_ja.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_ja.java @@ -74,7 +74,6 @@ public class TTYResources_ja extends java.util.ListResourceBundle { {"Array element is not a method", "\u914D\u5217\u8981\u7D20\u306F\u30E1\u30BD\u30C3\u30C9\u3067\u306F\u3042\u308A\u307E\u305B\u3093"}, {"Array index must be a integer type", "\u914D\u5217\u306E\u6DFB\u3048\u5B57\u306F\u6574\u6570\u578B\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059"}, {"base directory:", "\u30D9\u30FC\u30B9\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA: {0}"}, - {"bootclasspath:", "\u30D6\u30FC\u30C8\u30FB\u30AF\u30E9\u30B9\u30D1\u30B9: {0}"}, {"Breakpoint hit:", "\u30D2\u30C3\u30C8\u3057\u305F\u30D6\u30EC\u30FC\u30AF\u30DD\u30A4\u30F3\u30C8: "}, {"breakpoint", "\u30D6\u30EC\u30FC\u30AF\u30DD\u30A4\u30F3\u30C8{0}"}, {"Breakpoints set:", "\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u308B\u30D6\u30EC\u30FC\u30AF\u30DD\u30A4\u30F3\u30C8:"}, diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_zh_CN.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_zh_CN.java index 50790cb9d72..79dc9268da0 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_zh_CN.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_zh_CN.java @@ -74,7 +74,6 @@ public class TTYResources_zh_CN extends java.util.ListResourceBundle { {"Array element is not a method", "\u6570\u7EC4\u5143\u7D20\u4E0D\u662F\u65B9\u6CD5"}, {"Array index must be a integer type", "\u6570\u7EC4\u7D22\u5F15\u5FC5\u987B\u4E3A\u6574\u6570\u7C7B\u578B"}, {"base directory:", "\u57FA\u76EE\u5F55: {0}"}, - {"bootclasspath:", "\u5F15\u5BFC\u7C7B\u8DEF\u5F84: {0}"}, {"Breakpoint hit:", "\u65AD\u70B9\u547D\u4E2D: "}, {"breakpoint", "\u65AD\u70B9{0}"}, {"Breakpoints set:", "\u65AD\u70B9\u96C6:"}, diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java index 47e743483e3..28c3dfbfa3c 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java @@ -1439,7 +1439,7 @@ class VirtualMachineImpl extends MirrorImpl } public List bootClassPath() { - return Arrays.asList(getClasspath().bootclasspaths); + return Collections.emptyList(); } public String baseDirectory() { From ebbecb1b63493e47e7ad3a4d49698564ae1ac99a Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Thu, 21 Apr 2016 13:18:46 +0300 Subject: [PATCH 05/20] 8143921: nsk/jdi/ObjectReference/waitingThreads/waitingthreads003 fails with JVMTI_ERROR_INVALID_CLASS Skip invalid classes Reviewed-by: sspitsyn --- .../share/native/libjdwp/VirtualMachineImpl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c index 2718ad1e3a4..8e1639c5e2e 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c @@ -126,7 +126,7 @@ classesForSignature(PacketInputStream *in, PacketOutputStream *out) int writtenCount = 0; int i; - for (i=0; i Date: Mon, 25 Apr 2016 15:32:35 +0200 Subject: [PATCH 06/20] 8154529: some places in the invoke.c that use InvokeRequest* not protected with invokerLock Reviewed-by: sspitsyn --- .../share/native/libjdwp/invoker.c | 21 +++++++------------ .../share/native/libjdwp/invoker.h | 1 - 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c index cd1cd2f7dc0..3baf486c233 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.c @@ -277,12 +277,14 @@ invoker_enableInvokeRequests(jthread thread) JDI_ASSERT(thread); + debugMonitorEnter(invokerLock); request = threadControl_getInvokeRequest(thread); if (request == NULL) { EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request"); } request->available = JNI_TRUE; + debugMonitorExit(invokerLock); } jvmtiError @@ -738,30 +740,21 @@ invoker_completeInvokeRequest(jthread thread) } } -jboolean -invoker_isPending(jthread thread) -{ - InvokeRequest *request; - - JDI_ASSERT(thread); - request = threadControl_getInvokeRequest(thread); - if (request == NULL) { - EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request"); - } - return request->pending; -} - jboolean invoker_isEnabled(jthread thread) { InvokeRequest *request; + jboolean isEnabled; JDI_ASSERT(thread); + debugMonitorEnter(invokerLock); request = threadControl_getInvokeRequest(thread); if (request == NULL) { EXIT_ERROR(AGENT_ERROR_INVALID_THREAD, "getting thread invoke request"); } - return request->available; + isEnabled = request->available; + debugMonitorExit(invokerLock); + return isEnabled; } void diff --git a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.h b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.h index 29ecdb5d59c..e004ce6ef8e 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.h +++ b/jdk/src/jdk.jdwp.agent/share/native/libjdwp/invoker.h @@ -67,7 +67,6 @@ jvmtiError invoker_requestInvoke(jbyte invokeType, jbyte options, jint id, jboolean invoker_doInvoke(jthread thread); void invoker_completeInvokeRequest(jthread thread); -jboolean invoker_isPending(jthread thread); jboolean invoker_isEnabled(jthread thread); void invoker_detach(InvokeRequest *request); From 8f5fb772b45cce20bdb89917d931c22dc078c034 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 28 Apr 2016 00:38:21 -0700 Subject: [PATCH 07/20] 8153749: New capability can_generate_early_class_hook_events Add new capability Reviewed-by: alanb, dsamersoff --- jdk/src/java.base/share/native/include/jvmti.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/native/include/jvmti.h b/jdk/src/java.base/share/native/include/jvmti.h index 684fd2d7046..5f8835c0baa 100644 --- a/jdk/src/java.base/share/native/include/jvmti.h +++ b/jdk/src/java.base/share/native/include/jvmti.h @@ -704,7 +704,8 @@ typedef struct { unsigned int can_generate_resource_exhaustion_heap_events : 1; unsigned int can_generate_resource_exhaustion_threads_events : 1; unsigned int can_generate_early_vmstart : 1; - unsigned int : 6; + unsigned int can_generate_early_class_hook_events : 1; + unsigned int : 5; unsigned int : 16; unsigned int : 16; unsigned int : 16; From c7f8bb25dda6a009f279ea160a6d255fb4140fcb Mon Sep 17 00:00:00 2001 From: Nils Eliasson Date: Fri, 29 Apr 2016 09:40:08 +0200 Subject: [PATCH 08/20] 8142464: PlatformLoggerTest.java throws java.lang.RuntimeException: Logger test.logger.bar does not exist Test doesn't keep strong references to loggers Reviewed-by: kvn --- jdk/test/sun/util/logging/PlatformLoggerTest.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/jdk/test/sun/util/logging/PlatformLoggerTest.java b/jdk/test/sun/util/logging/PlatformLoggerTest.java index 0bf94d64a5a..913390161e4 100644 --- a/jdk/test/sun/util/logging/PlatformLoggerTest.java +++ b/jdk/test/sun/util/logging/PlatformLoggerTest.java @@ -31,7 +31,6 @@ * * @modules java.base/sun.util.logging * java.logging/sun.util.logging.internal - * @compile -XDignore.symbol.file PlatformLoggerTest.java * @run main/othervm PlatformLoggerTest */ @@ -42,25 +41,31 @@ import sun.util.logging.PlatformLogger; import static sun.util.logging.PlatformLogger.Level.*; public class PlatformLoggerTest { + + static Logger logger; + static PlatformLogger bar; + static PlatformLogger goo; + static PlatformLogger foo; + public static void main(String[] args) throws Exception { final String FOO_PLATFORM_LOGGER = "test.platformlogger.foo"; final String BAR_PLATFORM_LOGGER = "test.platformlogger.bar"; final String GOO_PLATFORM_LOGGER = "test.platformlogger.goo"; final String BAR_LOGGER = "test.logger.bar"; - PlatformLogger goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER); + goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER); // test the PlatformLogger methods testLogMethods(goo); // Create a platform logger using the default - PlatformLogger foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER); + foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER); checkPlatformLogger(foo, FOO_PLATFORM_LOGGER); // create a java.util.logging.Logger // now java.util.logging.Logger should be created for each platform logger - Logger logger = Logger.getLogger(BAR_LOGGER); + logger = Logger.getLogger(BAR_LOGGER); logger.setLevel(Level.WARNING); - PlatformLogger bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER); + bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER); checkPlatformLogger(bar, BAR_PLATFORM_LOGGER); // test the PlatformLogger methods From 528b2cc81a583705fd00075aa465256cd306be09 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Fri, 29 Apr 2016 15:17:46 -0400 Subject: [PATCH 09/20] 8155727: java/util/concurrent/locks/Lock/TimedAcquireLeak.java timeouts Fix regex pattern to handle possible (module@version) text Reviewed-by: ctornqvi, martin --- .../java/util/concurrent/locks/Lock/TimedAcquireLeak.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java index 7d6da0b255e..630f3796b8c 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java +++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, 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 @@ -167,7 +167,7 @@ public class TimedAcquireLeak { final String childPid, final String className) { final String regex = - "(?m)^ *[0-9]+: +([0-9]+) +[0-9]+ +\\Q"+className+"\\E$"; + "(?m)^ *[0-9]+: +([0-9]+) +[0-9]+ +\\Q"+className+"\\E(?:$| )"; final Callable objectsInUse = new Callable() { public Integer call() { Integer i = Integer.parseInt( From 3dfed24a479db9972f0ba9324ca27a9586fe2a45 Mon Sep 17 00:00:00 2001 From: Max Ockner Date: Fri, 29 Apr 2016 22:39:44 -0400 Subject: [PATCH 10/20] 8154110: Update class* and safepoint* logging subsystems Refactored logging tags in class and safepoint subsystems. Reviewed-by: coleenp, rehn, hseigel --- jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh | 2 +- jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh | 2 +- .../instrument/appendToClassLoaderSearch/ClassUnloadTest.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh index 3872f813ffd..a00c14077d6 100644 --- a/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh +++ b/jdk/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh @@ -106,7 +106,7 @@ done # run test ${TESTJAVA}${FS}bin${FS}java \ ${TESTVMOPTS} \ - -verbose:class -Xlog:classload -cp . \ + -verbose:class -Xlog:class+load -cp . \ -Dtest.classes=${TESTCLASSES} \ Starter cross # -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass \ diff --git a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh index 198cd70827a..1289b4c861e 100644 --- a/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh +++ b/jdk/test/java/lang/ClassLoader/deadlock/TestOneWayDelegate.sh @@ -102,7 +102,7 @@ done # run test ${TESTJAVA}${FS}bin${FS}java \ ${TESTVMOPTS} \ - -verbose:class -Xlog:classload -cp . \ + -verbose:class -Xlog:class+load -cp . \ -Dtest.classes=${TESTCLASSES} \ Starter one-way # -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass \ diff --git a/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh b/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh index f5bb3b83179..b428a59bb28 100644 --- a/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh +++ b/jdk/test/java/lang/instrument/appendToClassLoaderSearch/ClassUnloadTest.sh @@ -80,5 +80,5 @@ $JAR ${TESTTOOLVMOPTS} -cfm "${TESTCLASSES}"/ClassUnloadTest.jar "${MANIFEST}" \ # Finally we run the test (cd "${TESTCLASSES}"; \ - $JAVA ${TESTVMOPTS} -Xverify:none -Xlog:classunload \ + $JAVA ${TESTVMOPTS} -Xverify:none -Xlog:class+unload \ -javaagent:ClassUnloadTest.jar ClassUnloadTest "${OTHERDIR}" Bar.jar) From 4f53885343025864dedb15af3c22156242809e17 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 4 May 2016 17:17:28 +0300 Subject: [PATCH 11/20] 8155739: [TESTBUG] VarHandles/Unsafe tests for weakCAS should allow spurious failures Reviewed-by: psandoz, vlivanov, simonis --- .../invoke/VarHandles/VarHandleBaseTest.java | 3 +- .../VarHandleTestAccessBoolean.java | 1 - .../VarHandles/VarHandleTestAccessByte.java | 1 - .../VarHandles/VarHandleTestAccessChar.java | 1 - .../VarHandles/VarHandleTestAccessDouble.java | 1 - .../VarHandles/VarHandleTestAccessFloat.java | 1 - .../VarHandles/VarHandleTestAccessInt.java | 64 +++++++++++++------ .../VarHandles/VarHandleTestAccessLong.java | 64 +++++++++++++------ .../VarHandles/VarHandleTestAccessShort.java | 1 - .../VarHandles/VarHandleTestAccessString.java | 64 +++++++++++++------ .../VarHandleTestByteArrayAsChar.java | 1 - .../VarHandleTestByteArrayAsDouble.java | 43 +++++++++---- .../VarHandleTestByteArrayAsFloat.java | 43 +++++++++---- .../VarHandleTestByteArrayAsInt.java | 43 +++++++++---- .../VarHandleTestByteArrayAsLong.java | 43 +++++++++---- .../VarHandleTestByteArrayAsShort.java | 1 - .../VarHandleTestMethodHandleAccessInt.java | 63 ++++++++++++------ .../VarHandleTestMethodHandleAccessLong.java | 63 ++++++++++++------ ...VarHandleTestMethodHandleAccessString.java | 63 ++++++++++++------ .../X-VarHandleTestAccess.java.template | 63 ++++++++++++------ ...X-VarHandleTestByteArrayView.java.template | 42 ++++++++---- ...HandleTestMethodHandleAccess.java.template | 63 ++++++++++++------ 22 files changed, 512 insertions(+), 220 deletions(-) diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java index 241d821c00a..ee6205d1ed7 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java @@ -40,6 +40,7 @@ import static org.testng.Assert.*; abstract class VarHandleBaseTest { static final int ITERS = Integer.getInteger("iters", 1); + static final int WEAK_ATTEMPTS = Integer.getInteger("weakAttempts", 10); interface ThrowingRunnable { void run() throws Throwable; @@ -474,4 +475,4 @@ abstract class VarHandleBaseTest { assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType()); } } -} \ No newline at end of file +} diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java index 5590984e493..b22fc3e182a 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessBoolean extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java index f9c9d4fc31e..088a519e920 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessByte extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java index bd1174efc5a..18ff6542615 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessChar extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java index d8732d239b4..36c84e2f753 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessDouble extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java index 9976102d027..2ea2d9617be 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessFloat extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java index c78e5cb7199..25683af1097 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); @@ -402,22 +401,31 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(recv, 1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(recv, 1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) vh.get(recv); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = vh.weakCompareAndSetAcquire(recv, 2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(recv, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) vh.get(recv); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = vh.weakCompareAndSetRelease(recv, 1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(recv, 1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(recv); assertEquals(x, 2, "weakCompareAndSetRelease int"); } @@ -536,22 +544,31 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSet(1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) vh.get(); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = (boolean) vh.weakCompareAndSetAcquire(2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) vh.get(); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = (boolean) vh.weakCompareAndSetRelease( 1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(); assertEquals(x, 2, "weakCompareAndSetRelease int"); } @@ -673,22 +690,31 @@ public class VarHandleTestAccessInt extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(array, i, 1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, 1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) vh.get(array, i); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, 2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) vh.get(array, i); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, 1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, 1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(array, i); assertEquals(x, 2, "weakCompareAndSetRelease int"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java index f82ee67960e..2b44b4793f7 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); @@ -402,22 +401,31 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(recv, 1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(recv, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) vh.get(recv); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = vh.weakCompareAndSetAcquire(recv, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(recv, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) vh.get(recv); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = vh.weakCompareAndSetRelease(recv, 1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(recv, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(recv); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } @@ -536,22 +544,31 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSet(1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) vh.get(); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = (boolean) vh.weakCompareAndSetAcquire(2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) vh.get(); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = (boolean) vh.weakCompareAndSetRelease( 1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } @@ -673,22 +690,31 @@ public class VarHandleTestAccessLong extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(array, i, 1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) vh.get(array, i); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) vh.get(array, i); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, 1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(array, i); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java index d235e03a7bf..4ff25cc4a5f 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessShort extends VarHandleBaseTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java index 61e3690447c..1e876059a69 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java @@ -106,7 +106,6 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); @@ -416,22 +415,31 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(recv, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(recv, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) vh.get(recv); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = vh.weakCompareAndSetAcquire(recv, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(recv, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) vh.get(recv); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = vh.weakCompareAndSetRelease(recv, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(recv, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) vh.get(recv); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } @@ -548,22 +556,31 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSet("foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet("foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) vh.get(); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = (boolean) vh.weakCompareAndSetAcquire("bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire("bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) vh.get(); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = (boolean) vh.weakCompareAndSetRelease( "foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease("foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) vh.get(); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } @@ -683,22 +700,31 @@ public class VarHandleTestAccessString extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(array, i, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) vh.get(array, i); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) vh.get(array, i); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) vh.get(array, i); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java index e6941f5fa3c..842a9f55327 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java @@ -93,7 +93,6 @@ public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java index ec4b843b2aa..57635e95474 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java @@ -93,7 +93,6 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); @@ -678,22 +677,31 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet double value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease double"); } @@ -811,22 +819,31 @@ public class VarHandleTestByteArrayAsDouble extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet double value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire double"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease double"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease double"); double x = (double) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease double"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java index 57d37cbe523..23d5072e274 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java @@ -93,7 +93,6 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); @@ -678,22 +677,31 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet float value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease float"); } @@ -811,22 +819,31 @@ public class VarHandleTestByteArrayAsFloat extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet float value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire float"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease float"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease float"); float x = (float) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease float"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java index ae66477d3b6..91eee4f4775 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java @@ -93,7 +93,6 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); @@ -692,22 +691,31 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet int value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease int"); } @@ -834,22 +842,31 @@ public class VarHandleTestByteArrayAsInt extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet int value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire int"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease int"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java index ac08db2af5c..8adaf2b3428 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java @@ -93,7 +93,6 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); @@ -692,22 +691,31 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet long value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease long"); } @@ -834,22 +842,31 @@ public class VarHandleTestByteArrayAsLong extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet long value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire long"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease long"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java index 9742fbd2522..f554fb35058 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java @@ -93,7 +93,6 @@ public class VarHandleTestByteArrayAsShort extends VarHandleBaseByteArrayTest { assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); - assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java index 4e8de0c3bc8..4985136f2fd 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java @@ -208,22 +208,31 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 2, "weakCompareAndSetRelease int"); } @@ -342,22 +351,31 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( 1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2, "weakCompareAndSetRelease int"); } @@ -479,22 +497,31 @@ public class VarHandleTestMethodHandleAccessInt extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1, 2); - assertEquals(r, true, "weakCompareAndSet int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1, 2); + } + assertEquals(success, true, "weakCompareAndSet int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 2, "weakCompareAndSet int value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2, 1); - assertEquals(r, true, "weakCompareAndSetAcquire int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2, 1); + } + assertEquals(success, true, "weakCompareAndSetAcquire int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 1, "weakCompareAndSetAcquire int"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1, 2); - assertEquals(r, true, "weakCompareAndSetRelease int"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1, 2); + } + assertEquals(success, true, "weakCompareAndSetRelease int"); int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 2, "weakCompareAndSetRelease int"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java index 05efd70079b..59a3941c4db 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java @@ -208,22 +208,31 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } @@ -342,22 +351,31 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( 1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } @@ -479,22 +497,31 @@ public class VarHandleTestMethodHandleAccessLong extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1L, 2L); - assertEquals(r, true, "weakCompareAndSet long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSet long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 2L, "weakCompareAndSet long value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2L, 1L); - assertEquals(r, true, "weakCompareAndSetAcquire long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, 2L, 1L); + } + assertEquals(success, true, "weakCompareAndSetAcquire long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 1L, "weakCompareAndSetAcquire long"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1L, 2L); - assertEquals(r, true, "weakCompareAndSetRelease long"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, 1L, 2L); + } + assertEquals(success, true, "weakCompareAndSetRelease long"); long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, 2L, "weakCompareAndSetRelease long"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java index 62ef4ae7f37..eb2ed9d3c08 100644 --- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java +++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java @@ -208,22 +208,31 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } @@ -338,22 +347,31 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact("bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact("bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( "foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } @@ -471,22 +489,31 @@ public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSet String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSet String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, "bar", "weakCompareAndSet String value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "foo"); - assertEquals(r, true, "weakCompareAndSetAcquire String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "foo"); + } + assertEquals(success, true, "weakCompareAndSetAcquire String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, "foo", "weakCompareAndSetAcquire String"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, "foo", "bar"); - assertEquals(r, true, "weakCompareAndSetRelease String"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, "foo", "bar"); + } + assertEquals(success, true, "weakCompareAndSetRelease String"); String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, "bar", "weakCompareAndSetRelease String"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template index fb44c8bbb2b..dbee4cbb347 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template @@ -494,22 +494,31 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(recv, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(recv, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(recv); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = vh.weakCompareAndSetAcquire(recv, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(recv, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(recv); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = vh.weakCompareAndSetRelease(recv, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(recv, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(recv); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } @@ -670,22 +679,31 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { } { - boolean r = (boolean) vh.weakCompareAndSet($value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet($value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = (boolean) vh.weakCompareAndSetAcquire($value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire($value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = (boolean) vh.weakCompareAndSetRelease( $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease($value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } @@ -849,22 +867,31 @@ public class VarHandleTestAccess$Type$ extends VarHandleBaseTest { } { - boolean r = vh.weakCompareAndSet(array, i, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template index 1c323e2f195..12a0fcef8ad 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template @@ -848,22 +848,31 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$"); } @@ -994,22 +1003,31 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest { } { - boolean r = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value"); } { - boolean r = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$"); } { - boolean r = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) vh.get(array, i); assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$"); } diff --git a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template index 8e40761a4f3..a3b3aa5c43f 100644 --- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template +++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template @@ -209,22 +209,31 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } @@ -373,22 +382,31 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact($value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact($value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact($value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact($value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } @@ -540,22 +558,31 @@ public class VarHandleTestMethodHandleAccess$Type$ extends VarHandleBaseTest { } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSet $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSet $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, $value2$, "weakCompareAndSet $type$ value"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value2$, $value1$); - assertEquals(r, true, "weakCompareAndSetAcquire $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, $value2$, $value1$); + } + assertEquals(success, true, "weakCompareAndSetAcquire $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, $value1$, "weakCompareAndSetAcquire $type$"); } { - boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, $value1$, $value2$); - assertEquals(r, true, "weakCompareAndSetRelease $type$"); + boolean success = false; + for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) { + success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(array, i, $value1$, $value2$); + } + assertEquals(success, true, "weakCompareAndSetRelease $type$"); $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i); assertEquals(x, $value2$, "weakCompareAndSetRelease $type$"); } From 182152c38568d5f73b469d37e7b663677620d50d Mon Sep 17 00:00:00 2001 From: Harsha Wardhana B Date: Thu, 5 May 2016 01:52:03 -0700 Subject: [PATCH 12/20] 8154166: java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java fails with RuntimeException Fix the RuntimeException issue Reviewed-by: jbachorik --- .../management/MemoryMXBean/ResetPeakMemoryUsage.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java index b1f6e781044..dc85eb6bb03 100644 --- a/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java +++ b/jdk/test/java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java @@ -36,9 +36,13 @@ * @modules java.management * @build jdk.testlibrary.* ResetPeakMemoryUsage MemoryUtil RunUtil * @run main ResetPeakMemoryUsage + * @requires vm.opt.ExplicitGCInvokesConcurrent != "true" + * @requires vm.opt.ExplicitGCInvokesConcurrentAndUnloadsClasses != "true" + * @requires vm.opt.DisableExplicitGC != "true" */ import java.lang.management.*; +import java.lang.ref.WeakReference; import java.util.*; public class ResetPeakMemoryUsage { @@ -100,6 +104,7 @@ public class ResetPeakMemoryUsage { printMemoryUsage(usage0, peak0); obj = new Object[largeArraySize]; + WeakReference weakRef = new WeakReference<>(obj); MemoryUsage usage1 = mpool.getUsage(); MemoryUsage peak1 = mpool.getPeakUsage(); @@ -124,7 +129,11 @@ public class ResetPeakMemoryUsage { // The object is now garbage and do a GC // memory usage should drop obj = null; - mbean.gc(); + + //This will cause sure shot GC unlike Runtime.gc() invoked by mbean.gc() + while(weakRef.get() != null) { + mbean.gc(); + } MemoryUsage usage2 = mpool.getUsage(); MemoryUsage peak2 = mpool.getPeakUsage(); From b52c5bbd676a3d78caf1cee59abfa4846f540c9c Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Thu, 5 May 2016 11:44:01 -0700 Subject: [PATCH 13/20] 8147039: Incorrect locals and operands in compiled frames Implement stack walking using javaVFrame instead of vframeStream Reviewed-by: mchung, vlivanov --- .../lang/StackWalker/CountLocalSlots.java | 61 +++ .../lang/StackWalker/LocalsAndOperands.java | 378 ++++++++++++++---- .../java/lang/StackWalker/LocalsCrash.java | 74 ++++ 3 files changed, 439 insertions(+), 74 deletions(-) create mode 100644 jdk/test/java/lang/StackWalker/CountLocalSlots.java create mode 100644 jdk/test/java/lang/StackWalker/LocalsCrash.java diff --git a/jdk/test/java/lang/StackWalker/CountLocalSlots.java b/jdk/test/java/lang/StackWalker/CountLocalSlots.java new file mode 100644 index 00000000000..c78a4cb7bf4 --- /dev/null +++ b/jdk/test/java/lang/StackWalker/CountLocalSlots.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016 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 8147039 + * @summary Confirm locals[] always has expected length, even for "dead" locals + * @compile LocalsAndOperands.java + * @run testng/othervm -Xcomp CountLocalSlots + */ + +import org.testng.annotations.Test; +import java.lang.StackWalker.StackFrame; + +public class CountLocalSlots { + final static boolean debug = true; + + @Test(dataProvider = "provider", dataProviderClass = LocalsAndOperands.class) + public void countLocalSlots(StackFrame... frames) { + for (StackFrame frame : frames) { + if (debug) { + System.out.println("Running countLocalSlots"); + LocalsAndOperands.dumpStackWithLocals(frames); + } + // Confirm expected number of locals + String methodName = frame.getMethodName(); + Integer expectedObj = (Integer) LocalsAndOperands.Tester.NUM_LOCALS.get(methodName); + if (expectedObj == null) { + if (!debug) { LocalsAndOperands.dumpStackWithLocals(frames); } + throw new RuntimeException("No NUM_LOCALS entry for " + + methodName + "(). Update test?"); + } + Object[] locals = (Object[]) LocalsAndOperands.invokeGetLocals(frame); + if (locals.length != expectedObj) { + if (!debug) { LocalsAndOperands.dumpStackWithLocals(frames); } + throw new RuntimeException(methodName + "(): number of locals (" + + locals.length + ") did not match expected (" + expectedObj + ")"); + } + } + } +} diff --git a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java b/jdk/test/java/lang/StackWalker/LocalsAndOperands.java index 63a6731a164..b253ab27e81 100644 --- a/jdk/test/java/lang/StackWalker/LocalsAndOperands.java +++ b/jdk/test/java/lang/StackWalker/LocalsAndOperands.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016 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 @@ -23,17 +23,20 @@ /* * @test - * @bug 8020968 - * @summary Sanity test for locals and operands - * @run main LocalsAndOperands + * @bug 8020968 8147039 + * @summary Tests for locals and operands + * @run testng LocalsAndOperands */ +import org.testng.annotations.*; import java.lang.StackWalker.StackFrame; import java.lang.reflect.*; -import java.util.List; -import java.util.stream.Collectors; +import java.util.*; +import java.util.stream.*; public class LocalsAndOperands { + static final boolean debug = true; + static Class liveStackFrameClass; static Class primitiveValueClass; static StackWalker extendedWalker; @@ -41,92 +44,319 @@ public class LocalsAndOperands { static Method getOperands; static Method getMonitors; static Method primitiveType; - public static void main(String... args) throws Exception { - liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); - primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue"); - getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); - getLocals.setAccessible(true); + static { + try { + liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); + primitiveValueClass = Class.forName("java.lang.LiveStackFrame$PrimitiveValue"); - getOperands = liveStackFrameClass.getDeclaredMethod("getStack"); - getOperands.setAccessible(true); + getLocals = liveStackFrameClass.getDeclaredMethod("getLocals"); + getLocals.setAccessible(true); - getMonitors = liveStackFrameClass.getDeclaredMethod("getMonitors"); - getMonitors.setAccessible(true); + getOperands = liveStackFrameClass.getDeclaredMethod("getStack"); + getOperands.setAccessible(true); - primitiveType = primitiveValueClass.getDeclaredMethod("type"); - primitiveType.setAccessible(true); + getMonitors = liveStackFrameClass.getDeclaredMethod("getMonitors"); + getMonitors.setAccessible(true); - Method method = liveStackFrameClass.getMethod("getStackWalker"); - method.setAccessible(true); - extendedWalker = (StackWalker) method.invoke(null); - new LocalsAndOperands(extendedWalker, true).test(); + primitiveType = primitiveValueClass.getDeclaredMethod("type"); + primitiveType.setAccessible(true); - // no access to local and operands. - new LocalsAndOperands(StackWalker.getInstance(), false).test(); + Method method = liveStackFrameClass.getMethod("getStackWalker"); + method.setAccessible(true); + extendedWalker = (StackWalker) method.invoke(null); + } catch (Throwable t) { throw new RuntimeException(t); } } - private final StackWalker walker; - private final boolean extended; - LocalsAndOperands(StackWalker walker, boolean extended) { - this.walker = walker; - this.extended = extended; + /** Helper method to return a StackFrame's locals */ + static Object[] invokeGetLocals(StackFrame arg) { + try { + return (Object[]) getLocals.invoke(arg); + } catch (Exception e) { throw new RuntimeException(e); } } - synchronized void test() throws Exception { - int x = 10; - char c = 'z'; - String hi = "himom"; - long l = 1000000L; - double d = 3.1415926; + /***************** + * DataProviders * + *****************/ - List frames = walker.walk(s -> s.collect(Collectors.toList())); - if (extended) { - for (StackWalker.StackFrame f : frames) { - System.out.println("frame: " + f); - Object[] locals = (Object[]) getLocals.invoke(f); + /** Calls testLocals() and provides LiveStackFrames for testLocals* methods */ + @DataProvider + public static StackFrame[][] provider() { + return new StackFrame[][] { + new Tester().testLocals() + }; + } + + /** + * Calls testLocalsKeepAlive() and provides LiveStackFrames for testLocals* methods. + * Local variables in testLocalsKeepAlive() are ensured to not become dead. + */ + @DataProvider + public static StackFrame[][] keepAliveProvider() { + return new StackFrame[][] { + new Tester().testLocalsKeepAlive() + }; + } + + /** + * Provides StackFrames from a StackWalker without the LOCALS_AND_OPERANDS + * option. + */ + @DataProvider + public static StackFrame[][] noLocalsProvider() { + // Use default StackWalker + return new StackFrame[][] { + new Tester(StackWalker.getInstance(), true).testLocals() + }; + } + + /** + * Calls testLocals() and provides LiveStackFrames for *all* called methods, + * including test infrastructure (jtreg, testng, etc) + * + */ + @DataProvider + public static StackFrame[][] unfilteredProvider() { + return new StackFrame[][] { + new Tester(extendedWalker, false).testLocals() + }; + } + + /**************** + * Test methods * + ****************/ + + /** + * Check for expected local values and types in the LiveStackFrame + */ + @Test(dataProvider = "keepAliveProvider") + public static void checkLocalValues(StackFrame... frames) { + if (debug) { + System.out.println("Running checkLocalValues"); + dumpStackWithLocals(frames); + } + Arrays.stream(frames).filter(f -> f.getMethodName() + .equals("testLocalsKeepAlive")) + .forEach( + f -> { + Object[] locals = invokeGetLocals(f); for (int i = 0; i < locals.length; i++) { - System.out.format(" local %d: %s type %s\n", i, locals[i], type(locals[i])); + // Value + String expected = Tester.LOCAL_VALUES[i]; + Object observed = locals[i]; + if (expected != null /* skip nulls in golden values */ && + !expected.equals(observed.toString())) { + System.err.println("Local value mismatch:"); + if (!debug) { dumpStackWithLocals(frames); } + throw new RuntimeException("local " + i + " value is " + + observed + ", expected " + expected); + } - // check for non-null locals in LocalsAndOperands.test() - if (f.getClassName().equals("LocalsAndOperands") && - f.getMethodName().equals("test")) { - if (locals[i] == null) { - throw new RuntimeException("kept-alive locals should not be null"); - } + // Type + expected = Tester.LOCAL_TYPES[i]; + observed = type(locals[i]); + if (expected != null /* skip nulls in golden values */ && + !expected.equals(observed)) { + System.err.println("Local type mismatch:"); + if (!debug) { dumpStackWithLocals(frames); } + throw new RuntimeException("local " + i + " type is " + + observed + ", expected " + expected); } } - - Object[] operands = (Object[]) getOperands.invoke(f); - for (int i = 0; i < operands.length; i++) { - System.out.format(" operand %d: %s type %s%n", i, operands[i], - type(operands[i])); - } - - Object[] monitors = (Object[]) getMonitors.invoke(f); - for (int i = 0; i < monitors.length; i++) { - System.out.format(" monitor %d: %s%n", i, monitors[i]); - } } - } else { - for (StackFrame f : frames) { - if (liveStackFrameClass.isInstance(f)) { - throw new RuntimeException("should not be LiveStackFrame"); - } - } - } - // Use local variables so they stay alive - System.out.println("Stayin' alive: "+x+" "+c+" "+hi+" "+l+" "+d); + ); } - String type(Object o) throws Exception { - if (o == null) { - return "null"; - } else if (primitiveValueClass.isInstance(o)) { - char c = (char)primitiveType.invoke(o); - return String.valueOf(c); - } else { - return o.getClass().getName(); + /** + * Basic sanity check for locals and operands + */ + @Test(dataProvider = "provider") + public static void sanityCheck(StackFrame... frames) { + if (debug) { + System.out.println("Running sanityCheck"); } + try { + Stream stream = Arrays.stream(frames); + if (debug) { + stream.forEach(LocalsAndOperands::printLocals); + } else { + System.out.println(stream.count() + " frames"); + } + } catch (Throwable t) { + dumpStackWithLocals(frames); + throw t; + } + } + + /** + * Sanity check for locals and operands, including testng/jtreg frames + */ + @Test(dataProvider = "unfilteredProvider") + public static void unfilteredSanityCheck(StackFrame... frames) { + if (debug) { + System.out.println("Running unfilteredSanityCheck"); + } + try { + Stream stream = Arrays.stream(frames); + if (debug) { + stream.forEach(f -> { System.out.println(f + ": " + + invokeGetLocals(f).length + " locals"); } ); + } else { + System.out.println(stream.count() + " frames"); + } + } catch (Throwable t) { + dumpStackWithLocals(frames); + throw t; + } + } + + /** + * Test that LiveStackFrames are not provided with the default StackWalker + * options. + */ + @Test(dataProvider = "noLocalsProvider") + public static void withoutLocalsAndOperands(StackFrame... frames) { + for (StackFrame frame : frames) { + if (liveStackFrameClass.isInstance(frame)) { + throw new RuntimeException("should not be LiveStackFrame"); + } + } + } + + static class Tester { + private StackWalker walker; + private boolean filter = true; // Filter out testng/jtreg/etc frames? + + Tester() { + this.walker = extendedWalker; + } + + Tester(StackWalker walker, boolean filter) { + this.walker = walker; + this.filter = filter; + } + + /** + * Perform stackwalk without keeping local variables alive and return an + * array of the collected StackFrames + */ + private synchronized StackFrame[] testLocals() { + // Unused local variables will become dead + int x = 10; + char c = 'z'; + String hi = "himom"; + long l = 1000000L; + double d = 3.1415926; + + if (filter) { + return walker.walk(s -> s.filter(f -> TEST_METHODS.contains(f + .getMethodName())).collect(Collectors.toList())) + .toArray(new StackFrame[0]); + } else { + return walker.walk(s -> s.collect(Collectors.toList())) + .toArray(new StackFrame[0]); + } + } + + /** + * Perform stackwalk, keeping local variables alive, and return a list of + * the collected StackFrames + */ + private synchronized StackFrame[] testLocalsKeepAlive() { + int x = 10; + char c = 'z'; + String hi = "himom"; + long l = 1000000L; + double d = 3.1415926; + + List frames; + if (filter) { + frames = walker.walk(s -> s.filter(f -> TEST_METHODS.contains(f + .getMethodName())).collect(Collectors.toList())); + } else { + frames = walker.walk(s -> s.collect(Collectors.toList())); + } + + // Use local variables so they stay alive + System.out.println("Stayin' alive: "+x+" "+c+" "+hi+" "+l+" "+d); + return frames.toArray(new StackFrame[0]); // FIXME: convert to Array here + } + + // Expected values for locals in testLocals() & testLocalsKeepAlive() + // TODO: use real values instead of Strings, rebuild doubles & floats, etc + private final static String[] LOCAL_VALUES = new String[] { + null, // skip, LocalsAndOperands$Tester@XXX identity is different each run + "10", + "122", + "himom", + "0", + null, // skip, fix in 8156073 + null, // skip, fix in 8156073 + null, // skip, fix in 8156073 + "0" + }; + + // Expected types for locals in testLocals() & testLocalsKeepAlive() + // TODO: use real types + private final static String[] LOCAL_TYPES = new String[] { + null, // skip + "I", + "I", + "java.lang.String", + "I", + "I", + "I", + "I", + "I" + }; + + final static Map NUM_LOCALS = Map.of("testLocals", 8, + "testLocalsKeepAlive", + LOCAL_VALUES.length); + private final static Collection TEST_METHODS = NUM_LOCALS.keySet(); + } + + /** + * Print stack trace with locals + */ + public static void dumpStackWithLocals(StackFrame...frames) { + Arrays.stream(frames).forEach(LocalsAndOperands::printLocals); + } + + /** + * Print the StackFrame and an indexed list of its locals + */ + public static void printLocals(StackWalker.StackFrame frame) { + try { + System.out.println(frame); + Object[] locals = (Object[]) getLocals.invoke(frame); + for (int i = 0; i < locals.length; i++) { + System.out.format(" local %d: %s type %s\n", i, locals[i], type(locals[i])); + } + + Object[] operands = (Object[]) getOperands.invoke(frame); + for (int i = 0; i < operands.length; i++) { + System.out.format(" operand %d: %s type %s%n", i, operands[i], + type(operands[i])); + } + + Object[] monitors = (Object[]) getMonitors.invoke(frame); + for (int i = 0; i < monitors.length; i++) { + System.out.format(" monitor %d: %s%n", i, monitors[i]); + } + } catch (Exception e) { throw new RuntimeException(e); } + } + + private static String type(Object o) { + try { + if (o == null) { + return "null"; + } else if (primitiveValueClass.isInstance(o)) { + char c = (char)primitiveType.invoke(o); + return String.valueOf(c); + } else { + return o.getClass().getName(); + } + } catch(Exception e) { throw new RuntimeException(e); } } } diff --git a/jdk/test/java/lang/StackWalker/LocalsCrash.java b/jdk/test/java/lang/StackWalker/LocalsCrash.java new file mode 100644 index 00000000000..b50dd263f00 --- /dev/null +++ b/jdk/test/java/lang/StackWalker/LocalsCrash.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 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 8147039 + * @summary Test for -Xcomp crash that happened before 8147039 fix + * @run testng/othervm -Xcomp LocalsCrash + */ + +import org.testng.annotations.*; +import java.lang.reflect.*; +import java.util.List; +import java.util.stream.Collectors; + +public class LocalsCrash { + static Class liveStackFrameClass; + static Method getStackWalker; + + static { + try { + liveStackFrameClass = Class.forName("java.lang.LiveStackFrame"); + getStackWalker = liveStackFrameClass.getMethod("getStackWalker"); + getStackWalker.setAccessible(true); + } catch (Throwable t) { throw new RuntimeException(t); } + } + + private StackWalker walker; + + LocalsCrash() { + try { + walker = (StackWalker) getStackWalker.invoke(null); + } catch (Exception e) { throw new RuntimeException(e); } + } + + @Test + public void test00() { doStackWalk(); } + + @Test + public void test01() { doStackWalk(); } + + private synchronized List doStackWalk() { + try { + // Unused local variables will become dead + int x = 10; + char c = 'z'; + String hi = "himom"; + long l = 1000000L; + double d = 3.1415926; + + return walker.walk(s -> s.collect(Collectors.toList())); + } catch (Exception e) { throw new RuntimeException(e); } + } +} From 3d8d9fe7fa31fe7302e0d06274bf6980a53dd434 Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Thu, 5 May 2016 18:14:47 -0700 Subject: [PATCH 14/20] 8155794: Move Objects.checkIndex BiFunction accepting methods to an internal package Reviewed-by: chegar, shade, forax, vlivanov --- .../classes/java/lang/invoke/VarHandle.java | 4 +- .../lang/invoke/X-VarHandle.java.template | 36 +- .../X-VarHandleByteArrayView.java.template | 7 +- .../share/classes/java/util/Objects.java | 343 +---------------- .../jdk/internal/util/Preconditions.java | 346 ++++++++++++++++++ jdk/test/java/util/Objects/CheckIndex.java | 70 ++-- 6 files changed, 414 insertions(+), 392 deletions(-) create mode 100644 jdk/src/java.base/share/classes/jdk/internal/util/Preconditions.java diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java index cf869b3ebe7..8b555bcf7e2 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java @@ -26,6 +26,7 @@ package java.lang.invoke; import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; import java.lang.reflect.Method; @@ -34,7 +35,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; @@ -1380,7 +1380,7 @@ public abstract class VarHandle { } static final BiFunction, ArrayIndexOutOfBoundsException> - AIOOBE_SUPPLIER = Objects.outOfBoundsExceptionFormatter( + AIOOBE_SUPPLIER = Preconditions.outOfBoundsExceptionFormatter( new Function() { @Override public ArrayIndexOutOfBoundsException apply(String s) { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template index bcec64bd390..20514c79bf0 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template +++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template @@ -24,9 +24,11 @@ */ package java.lang.invoke; -import java.util.Objects; +import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; +import java.util.Objects; + import static java.lang.invoke.MethodHandleStatics.UNSAFE; #warn @@ -407,7 +409,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.get$Type$Volatile(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); } @ForceInline @@ -418,7 +420,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] UNSAFE.put$Type$Volatile(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } @@ -430,7 +432,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.get$Type$Opaque(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); } @ForceInline @@ -441,7 +443,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] UNSAFE.put$Type$Opaque(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } @@ -453,7 +455,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.get$Type$Acquire(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase); } @ForceInline @@ -464,7 +466,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] UNSAFE.put$Type$Release(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } #if[CAS] @@ -477,7 +479,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndSwap$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -490,7 +492,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndExchange$Type$Volatile(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -503,7 +505,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndExchange$Type$Acquire(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -516,7 +518,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.compareAndExchange$Type$Release(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -529,7 +531,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.weakCompareAndSwap$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -542,7 +544,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.weakCompareAndSwap$Type$Acquire(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -555,7 +557,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.weakCompareAndSwap$Type$Release(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(expected):expected}, {#if[Object]?handle.componentType.cast(value):value}); } @@ -568,7 +570,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.getAndSet$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, {#if[Object]?handle.componentType.cast(value):value}); } #end[CAS] @@ -582,7 +584,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.getAndAdd$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, value); } @@ -594,7 +596,7 @@ final class VarHandle$Type$s { $type$[] array = ($type$[]) oarray; #end[Object] return UNSAFE.getAndAdd$Type$(array, - (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, + (((long) Preconditions.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase, value) + value; } #end[AtomicAdd] diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template index bdc77a820d2..f0721b60778 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template +++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template @@ -25,6 +25,7 @@ package java.lang.invoke; import jdk.internal.misc.Unsafe; +import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; import java.nio.ByteBuffer; @@ -78,7 +79,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { @ForceInline static int index(byte[] ba, int index) { - return Objects.checkIndex(index, ba.length - ALIGN, null); + return Preconditions.checkIndex(index, ba.length - ALIGN, null); } @ForceInline @@ -287,14 +288,14 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase { @ForceInline static int index(ByteBuffer bb, int index) { - return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); + return Preconditions.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); } @ForceInline static int indexRO(ByteBuffer bb, int index) { if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY)) throw new ReadOnlyBufferException(); - return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); + return Preconditions.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null); } @ForceInline diff --git a/jdk/src/java.base/share/classes/java/util/Objects.java b/jdk/src/java.base/share/classes/java/util/Objects.java index 28b39d08969..dad583b9206 100644 --- a/jdk/src/java.base/share/classes/java/util/Objects.java +++ b/jdk/src/java.base/share/classes/java/util/Objects.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, 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 @@ -25,10 +25,9 @@ package java.util; -import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.util.Preconditions; +import jdk.internal.vm.annotation.ForceInline; -import java.util.function.BiFunction; -import java.util.function.Function; import java.util.function.Supplier; /** @@ -348,172 +347,6 @@ public final class Objects { return obj; } - /** - * Maps out-of-bounds values to a runtime exception. - * - * @param checkKind the kind of bounds check, whose name may correspond - * to the name of one of the range check methods, checkIndex, - * checkFromToIndex, checkFromIndexSize - * @param args the out-of-bounds arguments that failed the range check. - * If the checkKind corresponds a the name of a range check method - * then the bounds arguments are those that can be passed in order - * to the method. - * @param oobef the exception formatter that when applied with a checkKind - * and a list out-of-bounds arguments returns a runtime exception. - * If {@code null} then, it is as if an exception formatter was - * supplied that returns {@link IndexOutOfBoundsException} for any - * given arguments. - * @return the runtime exception - */ - private static RuntimeException outOfBounds( - BiFunction, ? extends RuntimeException> oobef, - String checkKind, - Integer... args) { - List largs = List.of(args); - RuntimeException e = oobef == null - ? null : oobef.apply(checkKind, largs); - return e == null - ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e; - } - - // Specific out-of-bounds exception producing methods that avoid - // the varargs-based code in the critical methods there by reducing their - // the byte code size, and therefore less likely to peturb inlining - - private static RuntimeException outOfBoundsCheckIndex( - BiFunction, ? extends RuntimeException> oobe, - int index, int length) { - return outOfBounds(oobe, "checkIndex", index, length); - } - - private static RuntimeException outOfBoundsCheckFromToIndex( - BiFunction, ? extends RuntimeException> oobe, - int fromIndex, int toIndex, int length) { - return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length); - } - - private static RuntimeException outOfBoundsCheckFromIndexSize( - BiFunction, ? extends RuntimeException> oobe, - int fromIndex, int size, int length) { - return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length); - } - - /** - * Returns an out-of-bounds exception formatter from an given exception - * factory. The exception formatter is a function that formats an - * out-of-bounds message from its arguments and applies that message to the - * given exception factory to produce and relay an exception. - * - *

The exception formatter accepts two arguments: a {@code String} - * describing the out-of-bounds range check that failed, referred to as the - * check kind; and a {@code List} containing the - * out-of-bound integer values that failed the check. The list of - * out-of-bound values is not modified. - * - *

Three check kinds are supported {@code checkIndex}, - * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding - * respectively to the specified application of an exception formatter as an - * argument to the out-of-bounds range check methods - * {@link #checkIndex(int, int, BiFunction) checkIndex}, - * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and - * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}. - * Thus a supported check kind corresponds to a method name and the - * out-of-bound integer values correspond to method argument values, in - * order, preceding the exception formatter argument (similar in many - * respects to the form of arguments required for a reflective invocation of - * such a range check method). - * - *

Formatter arguments conforming to such supported check kinds will - * produce specific exception messages describing failed out-of-bounds - * checks. Otherwise, more generic exception messages will be produced in - * any of the following cases: the check kind is supported but fewer - * or more out-of-bounds values are supplied, the check kind is not - * supported, the check kind is {@code null}, or the list of out-of-bound - * values is {@code null}. - * - * @apiNote - * This method produces an out-of-bounds exception formatter that can be - * passed as an argument to any of the supported out-of-bounds range check - * methods declared by {@code Objects}. For example, a formatter producing - * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a - * {@code static final} field as follows: - *

{@code
-     * static final
-     * BiFunction, ArrayIndexOutOfBoundsException> AIOOBEF =
-     *     outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new);
-     * }
- * The formatter instance {@code AIOOBEF} may be passed as an argument to an - * out-of-bounds range check method, such as checking if an {@code index} - * is within the bounds of a {@code limit}: - *
{@code
-     * checkIndex(index, limit, AIOOBEF);
-     * }
- * If the bounds check fails then the range check method will throw an - * {@code ArrayIndexOutOfBoundsException} with an appropriate exception - * message that is a produced from {@code AIOOBEF} as follows: - *
{@code
-     * AIOOBEF.apply("checkIndex", List.of(index, limit));
-     * }
- * - * @param f the exception factory, that produces an exception from a message - * where the message is produced and formatted by the returned - * exception formatter. If this factory is stateless and side-effect - * free then so is the returned formatter. - * Exceptions thrown by the factory are relayed to the caller - * of the returned formatter. - * @param the type of runtime exception to be returned by the given - * exception factory and relayed by the exception formatter - * @return the out-of-bounds exception formatter - */ - public static - BiFunction, X> outOfBoundsExceptionFormatter(Function f) { - // Use anonymous class to avoid bootstrap issues if this method is - // used early in startup - return new BiFunction, X>() { - @Override - public X apply(String checkKind, List args) { - return f.apply(outOfBoundsMessage(checkKind, args)); - } - }; - } - - private static String outOfBoundsMessage(String checkKind, List args) { - if (checkKind == null && args == null) { - return String.format("Range check failed"); - } else if (checkKind == null) { - return String.format("Range check failed: %s", args); - } else if (args == null) { - return String.format("Range check failed: %s", checkKind); - } - - int argSize = 0; - switch (checkKind) { - case "checkIndex": - argSize = 2; - break; - case "checkFromToIndex": - case "checkFromIndexSize": - argSize = 3; - break; - default: - } - - // Switch to default if fewer or more arguments than required are supplied - switch ((args.size() != argSize) ? "" : checkKind) { - case "checkIndex": - return String.format("Index %d out-of-bounds for length %d", - args.get(0), args.get(1)); - case "checkFromToIndex": - return String.format("Range [%d, %d) out-of-bounds for length %d", - args.get(0), args.get(1), args.get(2)); - case "checkFromIndexSize": - return String.format("Range [%d, %{@code length < 0}, which is implied from the former inequalities * * - *

This method behaves as if {@link #checkIndex(int, int, BiFunction)} - * was called with same out-of-bounds arguments and an exception formatter - * argument produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may - * be more efficient). - * * @param index the index * @param length the upper-bound (exclusive) of the range * @return {@code index} if it is within bounds of the range * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds * @since 9 */ + @ForceInline public static int checkIndex(int index, int length) { - return checkIndex(index, length, null); - } - - /** - * Checks if the {@code index} is within the bounds of the range from - * {@code 0} (inclusive) to {@code length} (exclusive). - * - *

The {@code index} is defined to be out-of-bounds if any of the - * following inequalities is true: - *

    - *
  • {@code index < 0}
  • - *
  • {@code index >= length}
  • - *
  • {@code length < 0}, which is implied from the former inequalities
  • - *
- * - *

If the {@code index} is out-of-bounds, then a runtime exception is - * thrown that is the result of applying the following arguments to the - * exception formatter: the name of this method, {@code checkIndex}; - * and an unmodifiable list integers whose values are, in order, the - * out-of-bounds arguments {@code index} and {@code length}. - * - * @param the type of runtime exception to throw if the arguments are - * out-of-bounds - * @param index the index - * @param length the upper-bound (exclusive) of the range - * @param oobef the exception formatter that when applied with this - * method name and out-of-bounds arguments returns a runtime - * exception. If {@code null} or returns {@code null} then, it is as - * if an exception formatter produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used - * instead (though it may be more efficient). - * Exceptions thrown by the formatter are relayed to the caller. - * @return {@code index} if it is within bounds of the range - * @throws X if the {@code index} is out-of-bounds and the exception - * formatter is non-{@code null} - * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds - * and the exception formatter is {@code null} - * @since 9 - * - * @implNote - * This method is made intrinsic in optimizing compilers to guide them to - * perform unsigned comparisons of the index and length when it is known the - * length is a non-negative value (such as that of an array length or from - * the upper bound of a loop) - */ - @HotSpotIntrinsicCandidate - public static - int checkIndex(int index, int length, - BiFunction, X> oobef) { - if (index < 0 || index >= length) - throw outOfBoundsCheckIndex(oobef, index, length); - return index; + return Preconditions.checkIndex(index, length, null); } /** @@ -608,12 +385,6 @@ public final class Objects { *

  • {@code length < 0}, which is implied from the former inequalities
  • * * - *

    This method behaves as if {@link #checkFromToIndex(int, int, int, BiFunction)} - * was called with same out-of-bounds arguments and an exception formatter - * argument produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may - * be more efficient). - * * @param fromIndex the lower-bound (inclusive) of the sub-range * @param toIndex the upper-bound (exclusive) of the sub-range * @param length the upper-bound (exclusive) the range @@ -623,54 +394,7 @@ public final class Objects { */ public static int checkFromToIndex(int fromIndex, int toIndex, int length) { - return checkFromToIndex(fromIndex, toIndex, length, null); - } - - /** - * Checks if the sub-range from {@code fromIndex} (inclusive) to - * {@code toIndex} (exclusive) is within the bounds of range from {@code 0} - * (inclusive) to {@code length} (exclusive). - * - *

    The sub-range is defined to be out-of-bounds if any of the following - * inequalities is true: - *

      - *
    • {@code fromIndex < 0}
    • - *
    • {@code fromIndex > toIndex}
    • - *
    • {@code toIndex > length}
    • - *
    • {@code length < 0}, which is implied from the former inequalities
    • - *
    - * - *

    If the sub-range is out-of-bounds, then a runtime exception is - * thrown that is the result of applying the following arguments to the - * exception formatter: the name of this method, {@code checkFromToIndex}; - * and an unmodifiable list integers whose values are, in order, the - * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}. - * - * @param the type of runtime exception to throw if the arguments are - * out-of-bounds - * @param fromIndex the lower-bound (inclusive) of the sub-range - * @param toIndex the upper-bound (exclusive) of the sub-range - * @param length the upper-bound (exclusive) the range - * @param oobef the exception formatter that when applied with this - * method name and out-of-bounds arguments returns a runtime - * exception. If {@code null} or returns {@code null} then, it is as - * if an exception formatter produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used - * instead (though it may be more efficient). - * Exceptions thrown by the formatter are relayed to the caller. - * @return {@code fromIndex} if the sub-range within bounds of the range - * @throws X if the sub-range is out-of-bounds and the exception factory - * function is non-{@code null} - * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and - * the exception factory function is {@code null} - * @since 9 - */ - public static - int checkFromToIndex(int fromIndex, int toIndex, int length, - BiFunction, X> oobef) { - if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) - throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length); - return fromIndex; + return Preconditions.checkFromToIndex(fromIndex, toIndex, length, null); } /** @@ -687,12 +411,6 @@ public final class Objects { *

  • {@code length < 0}, which is implied from the former inequalities
  • * * - *

    This method behaves as if {@link #checkFromIndexSize(int, int, int, BiFunction)} - * was called with same out-of-bounds arguments and an exception formatter - * argument produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} (though it may - * be more efficient). - * * @param fromIndex the lower-bound (inclusive) of the sub-interval * @param size the size of the sub-range * @param length the upper-bound (exclusive) of the range @@ -702,54 +420,7 @@ public final class Objects { */ public static int checkFromIndexSize(int fromIndex, int size, int length) { - return checkFromIndexSize(fromIndex, size, length, null); + return Preconditions.checkFromIndexSize(fromIndex, size, length, null); } - /** - * Checks if the sub-range from {@code fromIndex} (inclusive) to - * {@code fromIndex + size} (exclusive) is within the bounds of range from - * {@code 0} (inclusive) to {@code length} (exclusive). - * - *

    The sub-range is defined to be out-of-bounds if any of the following - * inequalities is true: - *

      - *
    • {@code fromIndex < 0}
    • - *
    • {@code size < 0}
    • - *
    • {@code fromIndex + size > length}, taking into account integer overflow
    • - *
    • {@code length < 0}, which is implied from the former inequalities
    • - *
    - * - *

    If the sub-range is out-of-bounds, then a runtime exception is - * thrown that is the result of applying the following arguments to the - * exception formatter: the name of this method, {@code checkFromIndexSize}; - * and an unmodifiable list integers whose values are, in order, the - * out-of-bounds arguments {@code fromIndex}, {@code size}, and - * {@code length}. - * - * @param the type of runtime exception to throw if the arguments are - * out-of-bounds - * @param fromIndex the lower-bound (inclusive) of the sub-interval - * @param size the size of the sub-range - * @param length the upper-bound (exclusive) of the range - * @param oobef the exception formatter that when applied with this - * method name and out-of-bounds arguments returns a runtime - * exception. If {@code null} or returns {@code null} then, it is as - * if an exception formatter produced from an invocation of - * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used - * instead (though it may be more efficient). - * Exceptions thrown by the formatter are relayed to the caller. - * @return {@code fromIndex} if the sub-range within bounds of the range - * @throws X if the sub-range is out-of-bounds and the exception factory - * function is non-{@code null} - * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and - * the exception factory function is {@code null} - * @since 9 - */ - public static - int checkFromIndexSize(int fromIndex, int size, int length, - BiFunction, X> oobef) { - if ((length | fromIndex | size) < 0 || size > length - fromIndex) - throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length); - return fromIndex; - } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/util/Preconditions.java b/jdk/src/java.base/share/classes/jdk/internal/util/Preconditions.java new file mode 100644 index 00000000000..cb1b748f620 --- /dev/null +++ b/jdk/src/java.base/share/classes/jdk/internal/util/Preconditions.java @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2016, 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 jdk.internal.util; + +import jdk.internal.HotSpotIntrinsicCandidate; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; + +/** + * Utility methods to check if state or arguments are correct. + * + */ +public class Preconditions { + + /** + * Maps out-of-bounds values to a runtime exception. + * + * @param checkKind the kind of bounds check, whose name may correspond + * to the name of one of the range check methods, checkIndex, + * checkFromToIndex, checkFromIndexSize + * @param args the out-of-bounds arguments that failed the range check. + * If the checkKind corresponds a the name of a range check method + * then the bounds arguments are those that can be passed in order + * to the method. + * @param oobef the exception formatter that when applied with a checkKind + * and a list out-of-bounds arguments returns a runtime exception. + * If {@code null} then, it is as if an exception formatter was + * supplied that returns {@link IndexOutOfBoundsException} for any + * given arguments. + * @return the runtime exception + */ + private static RuntimeException outOfBounds( + BiFunction, ? extends RuntimeException> oobef, + String checkKind, + Integer... args) { + List largs = List.of(args); + RuntimeException e = oobef == null + ? null : oobef.apply(checkKind, largs); + return e == null + ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e; + } + + private static RuntimeException outOfBoundsCheckIndex( + BiFunction, ? extends RuntimeException> oobe, + int index, int length) { + return outOfBounds(oobe, "checkIndex", index, length); + } + + private static RuntimeException outOfBoundsCheckFromToIndex( + BiFunction, ? extends RuntimeException> oobe, + int fromIndex, int toIndex, int length) { + return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length); + } + + private static RuntimeException outOfBoundsCheckFromIndexSize( + BiFunction, ? extends RuntimeException> oobe, + int fromIndex, int size, int length) { + return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length); + } + + /** + * Returns an out-of-bounds exception formatter from an given exception + * factory. The exception formatter is a function that formats an + * out-of-bounds message from its arguments and applies that message to the + * given exception factory to produce and relay an exception. + * + *

    The exception formatter accepts two arguments: a {@code String} + * describing the out-of-bounds range check that failed, referred to as the + * check kind; and a {@code List} containing the + * out-of-bound integer values that failed the check. The list of + * out-of-bound values is not modified. + * + *

    Three check kinds are supported {@code checkIndex}, + * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding + * respectively to the specified application of an exception formatter as an + * argument to the out-of-bounds range check methods + * {@link #checkIndex(int, int, BiFunction) checkIndex}, + * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and + * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}. + * Thus a supported check kind corresponds to a method name and the + * out-of-bound integer values correspond to method argument values, in + * order, preceding the exception formatter argument (similar in many + * respects to the form of arguments required for a reflective invocation of + * such a range check method). + * + *

    Formatter arguments conforming to such supported check kinds will + * produce specific exception messages describing failed out-of-bounds + * checks. Otherwise, more generic exception messages will be produced in + * any of the following cases: the check kind is supported but fewer + * or more out-of-bounds values are supplied, the check kind is not + * supported, the check kind is {@code null}, or the list of out-of-bound + * values is {@code null}. + * + * @apiNote + * This method produces an out-of-bounds exception formatter that can be + * passed as an argument to any of the supported out-of-bounds range check + * methods declared by {@code Objects}. For example, a formatter producing + * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a + * {@code static final} field as follows: + *

    {@code
    +     * static final
    +     * BiFunction, ArrayIndexOutOfBoundsException> AIOOBEF =
    +     *     outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new);
    +     * }
    + * The formatter instance {@code AIOOBEF} may be passed as an argument to an + * out-of-bounds range check method, such as checking if an {@code index} + * is within the bounds of a {@code limit}: + *
    {@code
    +     * checkIndex(index, limit, AIOOBEF);
    +     * }
    + * If the bounds check fails then the range check method will throw an + * {@code ArrayIndexOutOfBoundsException} with an appropriate exception + * message that is a produced from {@code AIOOBEF} as follows: + *
    {@code
    +     * AIOOBEF.apply("checkIndex", List.of(index, limit));
    +     * }
    + * + * @param f the exception factory, that produces an exception from a message + * where the message is produced and formatted by the returned + * exception formatter. If this factory is stateless and side-effect + * free then so is the returned formatter. + * Exceptions thrown by the factory are relayed to the caller + * of the returned formatter. + * @param the type of runtime exception to be returned by the given + * exception factory and relayed by the exception formatter + * @return the out-of-bounds exception formatter + */ + public static + BiFunction, X> outOfBoundsExceptionFormatter(Function f) { + // Use anonymous class to avoid bootstrap issues if this method is + // used early in startup + return new BiFunction, X>() { + @Override + public X apply(String checkKind, List args) { + return f.apply(outOfBoundsMessage(checkKind, args)); + } + }; + } + + private static String outOfBoundsMessage(String checkKind, List args) { + if (checkKind == null && args == null) { + return String.format("Range check failed"); + } else if (checkKind == null) { + return String.format("Range check failed: %s", args); + } else if (args == null) { + return String.format("Range check failed: %s", checkKind); + } + + int argSize = 0; + switch (checkKind) { + case "checkIndex": + argSize = 2; + break; + case "checkFromToIndex": + case "checkFromIndexSize": + argSize = 3; + break; + default: + } + + // Switch to default if fewer or more arguments than required are supplied + switch ((args.size() != argSize) ? "" : checkKind) { + case "checkIndex": + return String.format("Index %d out-of-bounds for length %d", + args.get(0), args.get(1)); + case "checkFromToIndex": + return String.format("Range [%d, %d) out-of-bounds for length %d", + args.get(0), args.get(1), args.get(2)); + case "checkFromIndexSize": + return String.format("Range [%d, %The {@code index} is defined to be out-of-bounds if any of the + * following inequalities is true: + *
      + *
    • {@code index < 0}
    • + *
    • {@code index >= length}
    • + *
    • {@code length < 0}, which is implied from the former inequalities
    • + *
    + * + *

    If the {@code index} is out-of-bounds, then a runtime exception is + * thrown that is the result of applying the following arguments to the + * exception formatter: the name of this method, {@code checkIndex}; + * and an unmodifiable list integers whose values are, in order, the + * out-of-bounds arguments {@code index} and {@code length}. + * + * @param the type of runtime exception to throw if the arguments are + * out-of-bounds + * @param index the index + * @param length the upper-bound (exclusive) of the range + * @param oobef the exception formatter that when applied with this + * method name and out-of-bounds arguments returns a runtime + * exception. If {@code null} or returns {@code null} then, it is as + * if an exception formatter produced from an invocation of + * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used + * instead (though it may be more efficient). + * Exceptions thrown by the formatter are relayed to the caller. + * @return {@code index} if it is within bounds of the range + * @throws X if the {@code index} is out-of-bounds and the exception + * formatter is non-{@code null} + * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds + * and the exception formatter is {@code null} + * @since 9 + * + * @implNote + * This method is made intrinsic in optimizing compilers to guide them to + * perform unsigned comparisons of the index and length when it is known the + * length is a non-negative value (such as that of an array length or from + * the upper bound of a loop) + */ + @HotSpotIntrinsicCandidate + public static + int checkIndex(int index, int length, + BiFunction, X> oobef) { + if (index < 0 || index >= length) + throw outOfBoundsCheckIndex(oobef, index, length); + return index; + } + + /** + * Checks if the sub-range from {@code fromIndex} (inclusive) to + * {@code toIndex} (exclusive) is within the bounds of range from {@code 0} + * (inclusive) to {@code length} (exclusive). + * + *

    The sub-range is defined to be out-of-bounds if any of the following + * inequalities is true: + *

      + *
    • {@code fromIndex < 0}
    • + *
    • {@code fromIndex > toIndex}
    • + *
    • {@code toIndex > length}
    • + *
    • {@code length < 0}, which is implied from the former inequalities
    • + *
    + * + *

    If the sub-range is out-of-bounds, then a runtime exception is + * thrown that is the result of applying the following arguments to the + * exception formatter: the name of this method, {@code checkFromToIndex}; + * and an unmodifiable list integers whose values are, in order, the + * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}. + * + * @param the type of runtime exception to throw if the arguments are + * out-of-bounds + * @param fromIndex the lower-bound (inclusive) of the sub-range + * @param toIndex the upper-bound (exclusive) of the sub-range + * @param length the upper-bound (exclusive) the range + * @param oobef the exception formatter that when applied with this + * method name and out-of-bounds arguments returns a runtime + * exception. If {@code null} or returns {@code null} then, it is as + * if an exception formatter produced from an invocation of + * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used + * instead (though it may be more efficient). + * Exceptions thrown by the formatter are relayed to the caller. + * @return {@code fromIndex} if the sub-range within bounds of the range + * @throws X if the sub-range is out-of-bounds and the exception factory + * function is non-{@code null} + * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and + * the exception factory function is {@code null} + * @since 9 + */ + public static + int checkFromToIndex(int fromIndex, int toIndex, int length, + BiFunction, X> oobef) { + if (fromIndex < 0 || fromIndex > toIndex || toIndex > length) + throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length); + return fromIndex; + } + + /** + * Checks if the sub-range from {@code fromIndex} (inclusive) to + * {@code fromIndex + size} (exclusive) is within the bounds of range from + * {@code 0} (inclusive) to {@code length} (exclusive). + * + *

    The sub-range is defined to be out-of-bounds if any of the following + * inequalities is true: + *

      + *
    • {@code fromIndex < 0}
    • + *
    • {@code size < 0}
    • + *
    • {@code fromIndex + size > length}, taking into account integer overflow
    • + *
    • {@code length < 0}, which is implied from the former inequalities
    • + *
    + * + *

    If the sub-range is out-of-bounds, then a runtime exception is + * thrown that is the result of applying the following arguments to the + * exception formatter: the name of this method, {@code checkFromIndexSize}; + * and an unmodifiable list integers whose values are, in order, the + * out-of-bounds arguments {@code fromIndex}, {@code size}, and + * {@code length}. + * + * @param the type of runtime exception to throw if the arguments are + * out-of-bounds + * @param fromIndex the lower-bound (inclusive) of the sub-interval + * @param size the size of the sub-range + * @param length the upper-bound (exclusive) of the range + * @param oobef the exception formatter that when applied with this + * method name and out-of-bounds arguments returns a runtime + * exception. If {@code null} or returns {@code null} then, it is as + * if an exception formatter produced from an invocation of + * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used + * instead (though it may be more efficient). + * Exceptions thrown by the formatter are relayed to the caller. + * @return {@code fromIndex} if the sub-range within bounds of the range + * @throws X if the sub-range is out-of-bounds and the exception factory + * function is non-{@code null} + * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and + * the exception factory function is {@code null} + * @since 9 + */ + public static + int checkFromIndexSize(int fromIndex, int size, int length, + BiFunction, X> oobef) { + if ((length | fromIndex | size) < 0 || size > length - fromIndex) + throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length); + return fromIndex; + } +} diff --git a/jdk/test/java/util/Objects/CheckIndex.java b/jdk/test/java/util/Objects/CheckIndex.java index c4efdb1c253..bcfa1d5b23d 100644 --- a/jdk/test/java/util/Objects/CheckIndex.java +++ b/jdk/test/java/util/Objects/CheckIndex.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016 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 @@ -23,11 +23,13 @@ /** * @test - * @summary IndexOutOfBoundsException check index tests + * @summary Objects.checkIndex/jdk.internal.util.Preconditions.checkIndex tests * @run testng CheckIndex - * @bug 8135248 8142493 + * @bug 8135248 8142493 8155794 + * @modules java.base/jdk.internal.util */ +import jdk.internal.util.Preconditions; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -95,7 +97,7 @@ public class CheckIndex { public void testCheckIndex(int index, int length, boolean withinBounds) { String expectedMessage = withinBounds ? null - : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). + : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). apply("checkIndex", List.of(index, length)).getMessage(); BiConsumer, IntSupplier> checker = (ec, s) -> { @@ -117,21 +119,21 @@ public class CheckIndex { }; checker.accept(AssertingOutOfBoundsException.class, - () -> Objects.checkIndex(index, length, - assertingOutOfBounds(expectedMessage, "checkIndex", index, length))); + () -> Preconditions.checkIndex(index, length, + assertingOutOfBounds(expectedMessage, "checkIndex", index, length))); checker.accept(IndexOutOfBoundsException.class, - () -> Objects.checkIndex(index, length, - assertingOutOfBoundsReturnNull("checkIndex", index, length))); + () -> Preconditions.checkIndex(index, length, + assertingOutOfBoundsReturnNull("checkIndex", index, length))); checker.accept(IndexOutOfBoundsException.class, - () -> Objects.checkIndex(index, length, null)); + () -> Preconditions.checkIndex(index, length, null)); checker.accept(IndexOutOfBoundsException.class, () -> Objects.checkIndex(index, length)); checker.accept(ArrayIndexOutOfBoundsException.class, - () -> Objects.checkIndex(index, length, - Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); + () -> Preconditions.checkIndex(index, length, + Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); checker.accept(StringIndexOutOfBoundsException.class, - () -> Objects.checkIndex(index, length, - Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); + () -> Preconditions.checkIndex(index, length, + Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); } @@ -157,7 +159,7 @@ public class CheckIndex { public void testCheckFromToIndex(int fromIndex, int toIndex, int length, boolean withinBounds) { String expectedMessage = withinBounds ? null - : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). + : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). apply("checkFromToIndex", List.of(fromIndex, toIndex, length)).getMessage(); BiConsumer, IntSupplier> check = (ec, s) -> { @@ -179,21 +181,21 @@ public class CheckIndex { }; check.accept(AssertingOutOfBoundsException.class, - () -> Objects.checkFromToIndex(fromIndex, toIndex, length, - assertingOutOfBounds(expectedMessage, "checkFromToIndex", fromIndex, toIndex, length))); + () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, + assertingOutOfBounds(expectedMessage, "checkFromToIndex", fromIndex, toIndex, length))); check.accept(IndexOutOfBoundsException.class, - () -> Objects.checkFromToIndex(fromIndex, toIndex, length, - assertingOutOfBoundsReturnNull("checkFromToIndex", fromIndex, toIndex, length))); + () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, + assertingOutOfBoundsReturnNull("checkFromToIndex", fromIndex, toIndex, length))); check.accept(IndexOutOfBoundsException.class, - () -> Objects.checkFromToIndex(fromIndex, toIndex, length, null)); + () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, null)); check.accept(IndexOutOfBoundsException.class, () -> Objects.checkFromToIndex(fromIndex, toIndex, length)); check.accept(ArrayIndexOutOfBoundsException.class, - () -> Objects.checkFromToIndex(fromIndex, toIndex, length, - Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); + () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, + Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); check.accept(StringIndexOutOfBoundsException.class, - () -> Objects.checkFromToIndex(fromIndex, toIndex, length, - Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); + () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, + Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); } @@ -226,7 +228,7 @@ public class CheckIndex { public void testCheckFromIndexSize(int fromIndex, int size, int length, boolean withinBounds) { String expectedMessage = withinBounds ? null - : Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). + : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new). apply("checkFromIndexSize", List.of(fromIndex, size, length)).getMessage(); BiConsumer, IntSupplier> check = (ec, s) -> { @@ -248,27 +250,27 @@ public class CheckIndex { }; check.accept(AssertingOutOfBoundsException.class, - () -> Objects.checkFromIndexSize(fromIndex, size, length, - assertingOutOfBounds(expectedMessage, "checkFromIndexSize", fromIndex, size, length))); + () -> Preconditions.checkFromIndexSize(fromIndex, size, length, + assertingOutOfBounds(expectedMessage, "checkFromIndexSize", fromIndex, size, length))); check.accept(IndexOutOfBoundsException.class, - () -> Objects.checkFromIndexSize(fromIndex, size, length, - assertingOutOfBoundsReturnNull("checkFromIndexSize", fromIndex, size, length))); + () -> Preconditions.checkFromIndexSize(fromIndex, size, length, + assertingOutOfBoundsReturnNull("checkFromIndexSize", fromIndex, size, length))); check.accept(IndexOutOfBoundsException.class, - () -> Objects.checkFromIndexSize(fromIndex, size, length, null)); + () -> Preconditions.checkFromIndexSize(fromIndex, size, length, null)); check.accept(IndexOutOfBoundsException.class, () -> Objects.checkFromIndexSize(fromIndex, size, length)); check.accept(ArrayIndexOutOfBoundsException.class, - () -> Objects.checkFromIndexSize(fromIndex, size, length, - Objects.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); + () -> Preconditions.checkFromIndexSize(fromIndex, size, length, + Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new))); check.accept(StringIndexOutOfBoundsException.class, - () -> Objects.checkFromIndexSize(fromIndex, size, length, - Objects.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); + () -> Preconditions.checkFromIndexSize(fromIndex, size, length, + Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new))); } @Test public void uniqueMessagesForCheckKinds() { BiFunction, IndexOutOfBoundsException> f = - Objects.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new); + Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new); List messages = new ArrayList<>(); // Exact arguments From 096e59e6c9d39e1704fb182a61c5debe748cc3e5 Mon Sep 17 00:00:00 2001 From: Sharath Ballal Date: Fri, 6 May 2016 11:47:45 +0300 Subject: [PATCH 15/20] 8154144: Tests in com/sun/jdi fails intermittently with "jdb input stream closed prematurely" Don't print stream closed message during shutdown Reviewed-by: dcubed, sla, dsamersoff --- .../tools/example/debug/tty/EventHandler.java | 6 +++++- .../com/sun/tools/example/debug/tty/TTY.java | 20 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java index fe6dd070f0d..cd416ccf24e 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/EventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -133,6 +133,10 @@ public class EventHandler implements Runnable { if (!vmDied) { vmDisconnectEvent(event); } + /* + * Inform jdb command line processor that jdb is being shutdown. JDK-8154144. + */ + ((TTY)notifier).setShuttingDown(true); Env.shutdown(shutdownMessageKey); return false; } else { diff --git a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java index 0bd403af2b9..ee716a55dcb 100644 --- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java +++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, 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 @@ -56,6 +56,16 @@ public class TTY implements EventNotifier { */ private static final String progname = "jdb"; + private volatile boolean shuttingDown = false; + + public void setShuttingDown(boolean s) { + shuttingDown = s; + } + + public boolean isShuttingDown() { + return shuttingDown; + } + @Override public void vmStartEvent(VMStartEvent se) { Thread.yield(); // fetch output @@ -750,7 +760,13 @@ public class TTY implements EventNotifier { while (true) { String ln = in.readLine(); if (ln == null) { - MessageOutput.println("Input stream closed."); + /* + * Jdb is being shutdown because debuggee exited, ignore any 'null' + * returned by readLine() during shutdown. JDK-8154144. + */ + if (!isShuttingDown()) { + MessageOutput.println("Input stream closed."); + } ln = "quit"; } From 85f537701c959dd32065f8e33a31999022dfbe5c Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 6 May 2016 17:59:49 +0300 Subject: [PATCH 16/20] 8155965: Unsafe.weakCompareAndSetVolatile entry points and intrinsics Reviewed-by: psandoz, vlivanov --- .../classes/jdk/internal/misc/Unsafe.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index beb64fd5155..fbd994da432 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -1271,6 +1271,13 @@ public final class Unsafe { return compareAndSwapObject(o, offset, expected, x); } + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapObjectVolatile(Object o, long offset, + Object expected, + Object x) { + return compareAndSwapObject(o, offset, expected, x); + } + /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. @@ -1325,6 +1332,13 @@ public final class Unsafe { return compareAndSwapInt(o, offset, expected, x); } + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapIntVolatile(Object o, long offset, + int expected, + int x) { + return compareAndSwapInt(o, offset, expected, x); + } + /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. @@ -1379,6 +1393,13 @@ public final class Unsafe { return compareAndSwapLong(o, offset, expected, x); } + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapLongVolatile(Object o, long offset, + long expected, + long x) { + return compareAndSwapLong(o, offset, expected, x); + } + /** * Fetches a reference value from a given Java variable, with volatile * load semantics. Otherwise identical to {@link #getObject(Object, long)} From 2b1fdef17a5fffe8ce0076a5e2d1b0e70aafd3ae Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Fri, 6 May 2016 15:59:27 -0700 Subject: [PATCH 17/20] 8150921: Update Unsafe getters/setters to use double-register variants Reviewed-by: dholmes, shade, psandoz, jrose --- .../classes/jdk/internal/misc/Unsafe.java | 213 ++++++++++++------ 1 file changed, 146 insertions(+), 67 deletions(-) diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index 735d1b86143..c7ee6a2f44f 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -33,6 +33,7 @@ import jdk.internal.reflect.Reflection; import jdk.internal.misc.VM; import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.vm.annotation.ForceInline; /** @@ -209,46 +210,103 @@ public final class Unsafe { /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native boolean getBoolean(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putBoolean(Object o, long offset, boolean x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native byte getByte(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putByte(Object o, long offset, byte x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native short getShort(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putShort(Object o, long offset, short x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native char getChar(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putChar(Object o, long offset, char x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native long getLong(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putLong(Object o, long offset, long x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native float getFloat(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putFloat(Object o, long offset, float x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native double getDouble(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putDouble(Object o, long offset, double x); + /** + * Fetches a native pointer from a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + *

    If the native pointer is less than 64 bits wide, it is extended as + * an unsigned number to a Java long. The pointer may be indexed by any + * given byte offset, simply by adding that offset (as a simple integer) to + * the long representing the pointer. The number of bytes actually read + * from the target address may be determined by consulting {@link + * #addressSize}. + * + * @see #allocateMemory + * @see #getInt(Object, long) + */ + @ForceInline + public long getAddress(Object o, long offset) { + if (ADDRESS_SIZE == 4) { + return Integer.toUnsignedLong(getInt(o, offset)); + } else { + return getLong(o, offset); + } + } + + /** + * Stores a native pointer into a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + *

    The number of bytes actually written at the target address may be + * determined by consulting {@link #addressSize}. + * + * @see #allocateMemory + * @see #putInt(Object, long, int) + */ + @ForceInline + public void putAddress(Object o, long offset, long x) { + if (ADDRESS_SIZE == 4) { + putInt(o, offset, (int)x); + } else { + putLong(o, offset, x); + } + } + // These read VM internal data. /** @@ -287,8 +345,10 @@ public final class Unsafe { * * @see #allocateMemory */ - @HotSpotIntrinsicCandidate - public native byte getByte(long address); + @ForceInline + public byte getByte(long address) { + return getByte(null, address); + } /** * Stores a value into a given memory address. If the address is zero, or @@ -297,75 +357,94 @@ public final class Unsafe { * * @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native void putByte(long address, byte x); + @ForceInline + public void putByte(long address, byte x) { + putByte(null, address, x); + } /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native short getShort(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putShort(long address, short x); - /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native char getChar(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putChar(long address, char x); - /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native int getInt(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putInt(long address, int x); - /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native long getLong(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putLong(long address, long x); - /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native float getFloat(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putFloat(long address, float x); - /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native double getDouble(long address); - /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putDouble(long address, double x); + @ForceInline + public short getShort(long address) { + return getShort(null, address); + } - /** - * Fetches a native pointer from a given memory address. If the address is - * zero, or does not point into a block obtained from {@link - * #allocateMemory}, the results are undefined. - * - *

    If the native pointer is less than 64 bits wide, it is extended as - * an unsigned number to a Java long. The pointer may be indexed by any - * given byte offset, simply by adding that offset (as a simple integer) to - * the long representing the pointer. The number of bytes actually read - * from the target address may be determined by consulting {@link - * #addressSize}. - * - * @see #allocateMemory - */ - @HotSpotIntrinsicCandidate - public native long getAddress(long address); + /** @see #putByte(long, byte) */ + @ForceInline + public void putShort(long address, short x) { + putShort(null, address, x); + } - /** - * Stores a native pointer into a given memory address. If the address is - * zero, or does not point into a block obtained from {@link - * #allocateMemory}, the results are undefined. - * - *

    The number of bytes actually written at the target address may be - * determined by consulting {@link #addressSize}. - * - * @see #getAddress(long) - */ - @HotSpotIntrinsicCandidate - public native void putAddress(long address, long x); + /** @see #getByte(long) */ + @ForceInline + public char getChar(long address) { + return getChar(null, address); + } + + /** @see #putByte(long, byte) */ + @ForceInline + public void putChar(long address, char x) { + putChar(null, address, x); + } + + /** @see #getByte(long) */ + @ForceInline + public int getInt(long address) { + return getInt(null, address); + } + + /** @see #putByte(long, byte) */ + @ForceInline + public void putInt(long address, int x) { + putInt(null, address, x); + } + + /** @see #getByte(long) */ + @ForceInline + public long getLong(long address) { + return getLong(null, address); + } + + /** @see #putByte(long, byte) */ + @ForceInline + public void putLong(long address, long x) { + putLong(null, address, x); + } + + /** @see #getByte(long) */ + @ForceInline + public float getFloat(long address) { + return getFloat(null, address); + } + + /** @see #putByte(long, byte) */ + @ForceInline + public void putFloat(long address, float x) { + putFloat(null, address, x); + } + + /** @see #getByte(long) */ + @ForceInline + public double getDouble(long address) { + return getDouble(null, address); + } + + /** @see #putByte(long, byte) */ + @ForceInline + public void putDouble(long address, double x) { + putDouble(null, address, x); + } + + /** @see #getAddress(Object, long) */ + @ForceInline + public long getAddress(long address) { + return getAddress(null, address); + } + + /** @see #putAddress(Object, long, long) */ + @ForceInline + public void putAddress(long address, long x) { + putAddress(null, address, x); + } From 529e4623639ff721a272e19b01191fb606abfac9 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Sat, 7 May 2016 10:32:56 +0900 Subject: [PATCH 18/20] 8156033: jhsdb jmap cannot set heapdump name Reviewed-by: dsamersoff --- .../sun/tools/jhsdb/BasicLauncherTest.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java b/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java index afba30c6055..b0f3b8d4f73 100644 --- a/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java +++ b/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java @@ -31,9 +31,12 @@ * @run main BasicLauncherTest */ +import static jdk.testlibrary.Asserts.assertTrue; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Arrays; @@ -99,7 +102,7 @@ public class BasicLauncherTest { System.out.println("Starting LingeredApp"); try { - theApp = LingeredApp.startApp(); + theApp = LingeredApp.startApp(Arrays.asList("-Xmx256m")); System.out.println("Starting " + toolName + " " + toolArgs.get(0) + " against " + theApp.getPid()); JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(toolName); @@ -129,6 +132,21 @@ public class BasicLauncherTest { launch(expectedMessage, Arrays.asList(toolArgs)); } + public static void testHeapDump() throws IOException { + File dump = new File("jhsdb.jmap.dump." + + System.currentTimeMillis() + ".hprof"); + if (dump.exists()) { + dump.delete(); + } + dump.deleteOnExit(); + + launch("heap written to", "jmap", + "--binaryheap", "--dumpfile=" + dump.getAbsolutePath()); + + assertTrue(dump.exists() && dump.isFile(), + "Could not create dump file " + dump.getAbsolutePath()); + } + public static void main(String[] args) throws IOException { @@ -145,6 +163,8 @@ public class BasicLauncherTest { launch("Java System Properties", "jinfo"); launch("java.threads", "jsnap"); + testHeapDump(); + // The test throws RuntimeException on error. // IOException is thrown if LingeredApp can't start because of some bad // environment condition From ae4d032d4143fd7b7bef4af7a8b7a75976f37707 Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Mon, 9 May 2016 23:41:59 +0300 Subject: [PATCH 19/20] 8155091: Remove SA related functions from tmtools Remove options that enables support for non-cooperative mode Reviewed-by: alanb, mchung, sla --- .../tools/attach/HotSpotVirtualMachine.java | 2 +- .../internal/vm/agent/spi/ToolProvider.java | 42 -- .../vm/agent/spi/ToolProviderFinder.java | 46 --- .../jdk.jcmd/share/classes/module-info.java | 5 - .../share/classes/sun/tools/jinfo/JInfo.java | 282 +++++-------- .../share/classes/sun/tools/jmap/JMap.java | 379 ++++++------------ .../classes/sun/tools/jstack/JStack.java | 144 +++---- .../heapconfig/JMapHeapConfigTest.java | 4 +- .../heapconfig/TmtoolTestScenario.java | 4 +- .../{JInfoHelper.java => BasicJInfoTest.java} | 67 ++-- .../sun/tools/jinfo/JInfoLauncherTest.java | 343 ---------------- .../jinfo/JInfoRunningProcessFlagTest.java | 129 ------ .../tools/jinfo/JInfoRunningProcessTest.java | 65 --- jdk/test/sun/tools/jinfo/JInfoSanityTest.java | 77 ---- jdk/test/sun/tools/jmap/BasicJMapTest.java | 17 +- .../sun/tools/jstack/BasicJStackTest.java | 2 - .../tools/jstack/DeadlockDetectionTest.java | 1 - 17 files changed, 333 insertions(+), 1276 deletions(-) delete mode 100644 jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java delete mode 100644 jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java rename jdk/test/sun/tools/{jmap => jhsdb}/heapconfig/JMapHeapConfigTest.java (98%) rename jdk/test/sun/tools/{jmap => jhsdb}/heapconfig/TmtoolTestScenario.java (97%) rename jdk/test/sun/tools/jinfo/{JInfoHelper.java => BasicJInfoTest.java} (51%) delete mode 100644 jdk/test/sun/tools/jinfo/JInfoLauncherTest.java delete mode 100644 jdk/test/sun/tools/jinfo/JInfoRunningProcessFlagTest.java delete mode 100644 jdk/test/sun/tools/jinfo/JInfoRunningProcessTest.java delete mode 100644 jdk/test/sun/tools/jinfo/JInfoSanityTest.java diff --git a/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java b/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java index 4a9562b069f..a5e965e5ec3 100644 --- a/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java +++ b/jdk/src/jdk.attach/share/classes/sun/tools/attach/HotSpotVirtualMachine.java @@ -258,7 +258,7 @@ public abstract class HotSpotVirtualMachine extends VirtualMachine { /* * Convenience method for simple commands */ - private InputStream executeCommand(String cmd, Object ... args) throws IOException { + public InputStream executeCommand(String cmd, Object ... args) throws IOException { try { return execute(cmd, args); } catch (AgentLoadException x) { diff --git a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java b/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java deleted file mode 100644 index 55be308348a..00000000000 --- a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProvider.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2016, 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 jdk.internal.vm.agent.spi; - -/** - * Service interface for jdk.hotspot.agent to provide the tools that - * jstack, jmap, jinfo will invoke, if present. - */ -public interface ToolProvider { - /** - * Returns the name of the tool provider - */ - String getName(); - - /** - * Invoke the tool provider with the given arguments - */ - void run(String... arguments); -} diff --git a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java b/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java deleted file mode 100644 index b96e6ae6239..00000000000 --- a/jdk/src/jdk.jcmd/share/classes/jdk/internal/vm/agent/spi/ToolProviderFinder.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2016, 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 jdk.internal.vm.agent.spi; - -import java.lang.reflect.Layer; -import java.util.HashMap; -import java.util.Map; -import java.util.ServiceLoader; - -public final class ToolProviderFinder { - private static final Map providers = init(); - - public static ToolProvider find(String name) { - return providers.get(name); - } - - private static Map init() { - Map providers = new HashMap<>(); - ServiceLoader.load(Layer.boot(), ToolProvider.class) - .forEach(p -> providers.putIfAbsent(p.getName(), p)); - return providers; - } -} diff --git a/jdk/src/jdk.jcmd/share/classes/module-info.java b/jdk/src/jdk.jcmd/share/classes/module-info.java index 4b8dbce1304..c78803b774c 100644 --- a/jdk/src/jdk.jcmd/share/classes/module-info.java +++ b/jdk/src/jdk.jcmd/share/classes/module-info.java @@ -26,9 +26,4 @@ module jdk.jcmd { requires jdk.attach; requires jdk.jvmstat; - - exports jdk.internal.vm.agent.spi to jdk.hotspot.agent; - - uses jdk.internal.vm.agent.spi.ToolProvider; } - diff --git a/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java b/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java index f19b6d159f0..dbfbaf2e25b 100644 --- a/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java +++ b/jdk/src/jdk.jcmd/share/classes/sun/tools/jinfo/JInfo.java @@ -32,8 +32,6 @@ import java.io.InputStream; import com.sun.tools.attach.VirtualMachine; import sun.tools.attach.HotSpotVirtualMachine; -import jdk.internal.vm.agent.spi.ToolProvider; -import jdk.internal.vm.agent.spi.ToolProviderFinder; /* * This class is the main class for the JInfo utility. It parses its arguments @@ -41,155 +39,73 @@ import jdk.internal.vm.agent.spi.ToolProviderFinder; * or an SA tool. */ final public class JInfo { - private static final String SA_JINFO_TOOL_NAME = "jinfo"; - private boolean useSA = false; - private String[] args = null; - - private JInfo(String[] args) throws IllegalArgumentException { - if (args.length == 0) { - throw new IllegalArgumentException(); - } - - int argCopyIndex = 0; - // First determine if we should launch SA or not - if (args[0].equals("-F")) { - // delete the -F - argCopyIndex = 1; - useSA = true; - } else if (args[0].equals("-flags") - || args[0].equals("-sysprops")) - { - if (args.length == 2) { - if (!isPid(args[1])) { - // If args[1] doesn't parse to a number then - // it must be the SA debug server - // (otherwise it is the pid) - useSA = true; - } - } else if (args.length == 3) { - // arguments include an executable and a core file - useSA = true; - } else { - throw new IllegalArgumentException(); - } - } else if (!args[0].startsWith("-")) { - if (args.length == 2) { - // the only arguments are an executable and a core file - useSA = true; - } else if (args.length == 1) { - if (!isPid(args[0])) { - // The only argument is not a PID; it must be SA debug - // server - useSA = true; - } - } else { - throw new IllegalArgumentException(); - } - } else if (args[0].equals("-h") || args[0].equals("-help")) { - if (args.length > 1) { - throw new IllegalArgumentException(); - } - } else if (args[0].equals("-flag")) { - if (args.length == 3) { - if (!isPid(args[2])) { - throw new IllegalArgumentException(); - } - } else { - throw new IllegalArgumentException(); - } - } else { - throw new IllegalArgumentException(); - } - - this.args = Arrays.copyOfRange(args, argCopyIndex, args.length); - } - - @SuppressWarnings("fallthrough") - private void execute() throws Exception { - if (args[0].equals("-h") - || args[0].equals("-help")) { - usage(0); - } - - if (useSA) { - // SA only supports -flags or -sysprops - if (args[0].startsWith("-")) { - if (!(args[0].equals("-flags") || args[0].equals("-sysprops"))) { - usage(1); - } - } - - // invoke SA which does it's own argument parsing - runTool(); - - } else { - // Now we can parse arguments for the non-SA case - String pid = null; - - switch(args[0]) { - case "-flag": - if (args.length != 3) { - usage(1); - } - String option = args[1]; - pid = args[2]; - flag(pid, option); - break; - case "-flags": - if (args.length != 2) { - usage(1); - } - pid = args[1]; - flags(pid); - break; - case "-sysprops": - if (args.length != 2) { - usage(1); - } - pid = args[1]; - sysprops(pid); - break; - case "-help": - case "-h": - usage(0); - // Fall through - default: - if (args.length == 1) { - // no flags specified, we do -sysprops and -flags - pid = args[0]; - sysprops(pid); - System.out.println(); - flags(pid); - System.out.println(); - commandLine(pid); - } else { - usage(1); - } - } - } - } public static void main(String[] args) throws Exception { - JInfo jinfo = null; - try { - jinfo = new JInfo(args); - jinfo.execute(); - } catch (IllegalArgumentException e) { + if (args.length == 0) { + usage(1); // no arguments + } + checkForUnsupportedOptions(args); + + boolean doFlag = false; + boolean doFlags = false; + boolean doSysprops = false; + + // Parse the options (arguments starting with "-" ) + int optionCount = 0; + while (optionCount < args.length) { + String arg = args[optionCount]; + if (!arg.startsWith("-")) { + break; + } + + optionCount++; + + if (arg.equals("-help") || arg.equals("-h")) { + usage(0); + } + + if (arg.equals("-flag")) { + doFlag = true; + continue; + } + + if (arg.equals("-flags")) { + doFlags = true; + continue; + } + + if (arg.equals("-sysprops")) { + doSysprops = true; + continue; + } + } + + // Next we check the parameter count. -flag allows extra parameters + int paramCount = args.length - optionCount; + if ((doFlag && paramCount != 2) || (paramCount != 1)) { usage(1); } - } - private static boolean isPid(String arg) { - return arg.matches("[0-9]+"); - } - - // Invoke SA tool with the given arguments - private void runTool() throws Exception { - ToolProvider tool = ToolProviderFinder.find(SA_JINFO_TOOL_NAME); - if (tool == null) { - usage(1); + if (!doFlag && !doFlags && !doSysprops) { + // Print flags and sysporps if no options given + sysprops(args[optionCount]); + System.out.println(); + flags(args[optionCount]); + System.out.println(); + commandLine(args[optionCount]); + } + + if (doFlag) { + flag(args[optionCount+1], args[optionCount]); + } + else { + if (doFlags) { + flags(args[optionCount]); + } + else if (doSysprops) { + sysprops(args[optionCount]); + } } - tool.run(args); } private static void flag(String pid, String option) throws IOException { @@ -274,46 +190,50 @@ final public class JInfo { vm.detach(); } + private static void checkForUnsupportedOptions(String[] args) { + // Check arguments for -F, and non-numeric value + // and warn the user that SA is not supported anymore - // print usage message - private static void usage(int exit) { - boolean usageSA = ToolProviderFinder.find(SA_JINFO_TOOL_NAME) != null; + int paramCount = 0; - System.err.println("Usage:"); - if (usageSA) { - System.err.println(" jinfo [option] "); - System.err.println(" (to connect to a running process)"); - System.err.println(" jinfo -F [option] "); - System.err.println(" (to connect to a hung process)"); - System.err.println(" jinfo [option] "); - System.err.println(" (to connect to a core file)"); - System.err.println(" jinfo [option] [server_id@]"); - System.err.println(" (to connect to remote debug server)"); - System.err.println(""); - System.err.println("where