From 8fe7a15c08336c8428c4470605da77c2fa4bff43 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Fri, 1 Nov 2013 10:08:10 +0100 Subject: [PATCH 01/74] 8027692: Remove java/lang/management/MemoryMXBean/LowMemoryTest2.sh from ProblemList.txt Reviewed-by: stefank, alanb --- jdk/test/ProblemList.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index ea99549a0f7..202f703b713 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -128,9 +128,6 @@ java/lang/management/ThreadMXBean/ThreadStateTest.java generic-all # 7067973 java/lang/management/MemoryMXBean/CollectionUsageThreshold.java generic-all -# 7196801 -java/lang/management/MemoryMXBean/LowMemoryTest2.sh generic-all - # 8021230 java/lang/ThreadLocal/ThreadLocalSupplierTest.java generic-all From fdbeb8e0fb4a958fb8a95e70466e51a7acfc7375 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Fri, 1 Nov 2013 15:10:10 +0100 Subject: [PATCH 02/74] 8027705: com/sun/jdi/JdbMethodExitTest.sh fails when a background thread is generating events Reviewed-by: dcubed --- jdk/test/com/sun/jdi/JdbMethodExitTest.sh | 20 +++++---- jdk/test/com/sun/jdi/ShellScaffold.sh | 52 +++++++++++++++++++++++ 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/jdk/test/com/sun/jdi/JdbMethodExitTest.sh b/jdk/test/com/sun/jdi/JdbMethodExitTest.sh index 52c0fe7becf..ab00816ca6e 100644 --- a/jdk/test/com/sun/jdi/JdbMethodExitTest.sh +++ b/jdk/test/com/sun/jdi/JdbMethodExitTest.sh @@ -156,7 +156,7 @@ class $classname { // a resume. $classname xx = new $classname(); - + System.out.println("threadid="+Thread.currentThread().getId()); bkpt(); // test all possible return types @@ -197,6 +197,8 @@ dojdbCmds() # test all possible return types runToBkpt @1 + debuggeeMatchRegexp "s/threadid=\(.*\)/\1/g" + threadid=$? cmd untrace cmd trace methods @@ -226,7 +228,7 @@ dojdbCmds() # trace exit of methods with all the return values # (but just check a couple of them) - cmd trace go exits + cmd trace go method exits $threadid cmd cont jdbFailIfNotPresent "instance of JdbMethodExitTest" jdbFailIfNotPresent "return value = 8" @@ -235,7 +237,7 @@ dojdbCmds() cmd step up - cmd trace methods + cmd trace methods $threadid cmd cont jdbFailIfNotPresent "Method entered:" cmd cont @@ -243,7 +245,9 @@ dojdbCmds() cmd step up - cmd trace go methods + cmd trace go methods $threadid + cmd cont + cmd cont cmd cont jdbFailIfNotPresent "Method entered: \"thread=main\", JdbMethodExitTest.traceMethods1" jdbFailIfNotPresent 'Method exited: .* JdbMethodExitTest.traceMethods1' @@ -251,14 +255,14 @@ dojdbCmds() cmd step up - cmd trace method exits + cmd trace method exits $threadid cmd cont jdbFailIfNotPresent "Method exited: return value = \"traceExits\"" cmd untrace cmd step up - cmd trace go method exits + cmd trace go method exits $threadid cmd cont jdbFailIfNotPresent 'Method exited: .* JdbMethodExitTest.traceExits1' cmd untrace @@ -266,7 +270,7 @@ dojdbCmds() cmd step # step into traceExit() - cmd trace method exit + cmd trace method exit $threadid cmd cont jdbFailIfNotPresent "Method exited: return value = \"traceExit\"" cmd untrace @@ -275,7 +279,7 @@ dojdbCmds() cmd step cmd step # skip over setting return value in caller :-( - cmd trace go method exit + cmd trace go method exit $threadid cmd cont jdbFailIfNotPresent 'Method exited: .*JdbMethodExitTest.traceExit1' cmd quit diff --git a/jdk/test/com/sun/jdi/ShellScaffold.sh b/jdk/test/com/sun/jdi/ShellScaffold.sh index d8635e3dda9..6ed55c1ae91 100644 --- a/jdk/test/com/sun/jdi/ShellScaffold.sh +++ b/jdk/test/com/sun/jdi/ShellScaffold.sh @@ -1004,6 +1004,50 @@ grepForString() return $stat } +# $1 is the filename, $2 is the regexp to match and return, +# $3 is the number of lines to search (from the end) +matchRegexp() +{ + if [ -z "$3" ] ; then + theCmd=cat + else + theCmd="tail -$3" + fi + + case "$2" in + *\>*) + # Target string contains a '>' so we better not ignore it + res=`$theCmd $1 | sed -e "$2"` + ;; + *) + # Target string does not contain a '>'. + # NOTE: if $1 does not end with a new line, piping it to sed + # doesn't include the chars on the last line. Detect this + # case, and add a new line. + theFile="$1" + if [ `tail -1 "$theFile" | wc -l | sed -e 's@ @@g'` = 0 ] ; then + # The target file doesn't end with a new line so we have + # add one to a copy of the target file so the sed command + # below can filter that last line. + cp "$theFile" "$theFile.tmp" + theFile="$theFile.tmp" + echo >> "$theFile" + fi + + # See bug 6220903. Sometimes the jdb prompt chars ('> ') can + # get interleaved in the target file which can keep us from + # matching the target string. + res=`$theCmd "$theFile" | sed -e 's@> @@g' -e 's@>@@g' \ + | sed -e "$2"` + if [ "$theFile" != "$1" ]; then + # remove the copy of the target file + rm -f "$theFile" + fi + unset theFile + esac + return $res +} + # $1 is the filename, $2 is the string to look for, # $3 is the number of lines to search (from the end) failIfPresent() @@ -1058,6 +1102,14 @@ debuggeeFailIfPresent() failIfPresent $debuggeeOutFile "$1" $2 } +# match and return the output from the regexp $1 in the debuggee output +# $2 is the number of lines to search (from the end) +debuggeeMatchRegexp() +{ + matchRegexp $debuggeeOutFile "$1" $2 +} + + # This should really be named 'done' instead of pass. pass() { From f7db4eb56b4c34653120d684d0aabd96b9af18ab Mon Sep 17 00:00:00 2001 From: Dan Xu Date: Fri, 1 Nov 2013 14:40:03 -0700 Subject: [PATCH 03/74] 8027624: com/sun/crypto/provider/KeyFactory/TestProviderLeak.java unstable again Reviewed-by: wetmore --- .../crypto/provider/KeyFactory/TestProviderLeak.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java b/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java index 04fa96a9813..83b2c690410 100644 --- a/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java +++ b/jdk/test/com/sun/crypto/provider/KeyFactory/TestProviderLeak.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6578538 + * @bug 6578538 8027624 * @summary com.sun.crypto.provider.SunJCE instance leak using KRB5 and * LoginContext * @author Brad Wetmore @@ -89,10 +89,6 @@ public class TestProviderLeak { } public static void main(String [] args) throws Exception { - // Eat up memory - Deque dummyData = eatupMemory(); - assert (dummyData != null); - // Prepare the test final SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1", "SunJCE"); @@ -107,6 +103,10 @@ public class TestProviderLeak { } }; + // Eat up memory + Deque dummyData = eatupMemory(); + assert (dummyData != null); + // Start testing iteration try { for (int i = 0; i <= 1000; i++) { From bb01d169de996d6a374930671d0293cdfb2a4567 Mon Sep 17 00:00:00 2001 From: Sergey Kuksenko Date: Sat, 2 Nov 2013 20:08:10 -0700 Subject: [PATCH 04/74] 8024635: Caching MethodType's descriptor string improves lambda linkage performance Better interpreted and compiled performance of operations in MethodType important to LambdaMetafactory. Reviewed-by: jrose, twisti, mchung --- .../classes/java/lang/invoke/MethodType.java | 51 ++++++++++++------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodType.java b/jdk/src/share/classes/java/lang/invoke/MethodType.java index f8e0967c7af..781ecfc56bd 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodType.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodType.java @@ -32,6 +32,7 @@ import java.lang.ref.ReferenceQueue; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentHashMap; import sun.invoke.util.BytecodeDescriptor; @@ -98,13 +99,25 @@ class MethodType implements java.io.Serializable { private @Stable MethodTypeForm form; // erased form, plus cached data about primitives private @Stable MethodType wrapAlt; // alternative wrapped/unwrapped version private @Stable Invokers invokers; // cache of handy higher-order adapters + private @Stable String methodDescriptor; // cache for toMethodDescriptorString /** * Check the given parameters for validity and store them into the final fields. */ - private MethodType(Class rtype, Class[] ptypes) { + private MethodType(Class rtype, Class[] ptypes, boolean trusted) { checkRtype(rtype); checkPtypes(ptypes); + this.rtype = rtype; + // defensively copy the array passed in by the user + this.ptypes = trusted ? ptypes : Arrays.copyOf(ptypes, ptypes.length); + } + + /** + * Construct a temporary unchecked instance of MethodType for use only as a key to the intern table. + * Does not check the given parameters for validity, and must be discarded after it is used as a searching key. + * The parameters are reversed for this constructor, so that is is not accidentally used. + */ + private MethodType(Class[] ptypes, Class rtype) { this.rtype = rtype; this.ptypes = ptypes; } @@ -146,20 +159,21 @@ class MethodType implements java.io.Serializable { /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1; // deduct one more for invoker private static void checkRtype(Class rtype) { - rtype.equals(rtype); // null check + Objects.requireNonNull(rtype); } - private static int checkPtype(Class ptype) { - ptype.getClass(); //NPE + private static void checkPtype(Class ptype) { + Objects.requireNonNull(ptype); if (ptype == void.class) throw newIllegalArgumentException("parameter type cannot be void"); - if (ptype == double.class || ptype == long.class) return 1; - return 0; } /** Return number of extra slots (count of long/double args). */ private static int checkPtypes(Class[] ptypes) { int slots = 0; for (Class ptype : ptypes) { - slots += checkPtype(ptype); + checkPtype(ptype); + if (ptype == double.class || ptype == long.class) { + slots++; + } } checkSlotCount(ptypes.length + slots); return slots; @@ -284,20 +298,16 @@ class MethodType implements java.io.Serializable { */ /*trusted*/ static MethodType makeImpl(Class rtype, Class[] ptypes, boolean trusted) { + MethodType mt = internTable.get(new MethodType(ptypes, rtype)); + if (mt != null) + return mt; if (ptypes.length == 0) { ptypes = NO_PTYPES; trusted = true; } - MethodType mt1 = new MethodType(rtype, ptypes); - MethodType mt0 = internTable.get(mt1); - if (mt0 != null) - return mt0; - if (!trusted) - // defensively copy the array passed in by the user - mt1 = new MethodType(rtype, ptypes.clone()); + mt = new MethodType(rtype, ptypes, trusted); // promote the object to the Real Thing, and reprobe - MethodTypeForm form = MethodTypeForm.findForm(mt1); - mt1.form = form; - return internTable.add(mt1); + mt.form = MethodTypeForm.findForm(mt); + return internTable.add(mt); } private static final MethodType[] objectOnlyTypes = new MethodType[20]; @@ -919,7 +929,12 @@ class MethodType implements java.io.Serializable { * @return the bytecode type descriptor representation */ public String toMethodDescriptorString() { - return BytecodeDescriptor.unparse(this); + String desc = methodDescriptor; + if (desc == null) { + desc = BytecodeDescriptor.unparse(this); + methodDescriptor = desc; + } + return desc; } /*non-public*/ static String toFieldDescriptorString(Class cls) { From bd40c9b63dbc83449356a4f7f50bb6f20f27a2ff Mon Sep 17 00:00:00 2001 From: Tristan Yan Date: Mon, 4 Nov 2013 06:58:30 -0500 Subject: [PATCH 05/74] 8025198: Intermittent test failure: java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java Reviewed-by: martin, dholmes --- jdk/makefiles/CompileLaunchers.gmk | 2 +- jdk/makefiles/lib/CoreLibraries.gmk | 2 +- jdk/src/share/bin/java.c | 54 +++++++++++++++---- .../ThreadPoolExecutor/ThrowingTasks.java | 16 +++++- 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/jdk/makefiles/CompileLaunchers.gmk b/jdk/makefiles/CompileLaunchers.gmk index af5b3583758..2de3900acd0 100644 --- a/jdk/makefiles/CompileLaunchers.gmk +++ b/jdk/makefiles/CompileLaunchers.gmk @@ -154,7 +154,7 @@ define SetupLauncher $(ORIGIN_ARG) \ $$($1_LDFLAGS), \ LDFLAGS_macosx := $(call SET_SHARED_LIBRARY_NAME,$1), \ - LDFLAGS_linux := -lpthread \ + LDFLAGS_linux := -lpthread -lrt \ $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \ LDFLAGS_solaris := $$($1_LDFLAGS_solaris) \ $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \ diff --git a/jdk/makefiles/lib/CoreLibraries.gmk b/jdk/makefiles/lib/CoreLibraries.gmk index 29c1d5fc08a..a631cf80cde 100644 --- a/jdk/makefiles/lib/CoreLibraries.gmk +++ b/jdk/makefiles/lib/CoreLibraries.gmk @@ -414,7 +414,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJLI, \ LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \ LDFLAGS_macosx := -framework Cocoa -framework Security -framework ApplicationServices, \ LDFLAGS_SUFFIX_solaris := $(LIBZ) $(LIBDL) -lc, \ - LDFLAGS_SUFFIX_linux := $(LIBZ) $(LIBDL) -lc -lpthread, \ + LDFLAGS_SUFFIX_linux := $(LIBZ) $(LIBDL) -lc -lpthread -lrt, \ LDFLAGS_SUFFIX_macosx := $(LIBZ), \ LDFLAGS_SUFFIX_windows := \ -export:JLI_Launch \ diff --git a/jdk/src/share/bin/java.c b/jdk/src/share/bin/java.c index 73c532676b3..9d1b2bf0209 100644 --- a/jdk/src/share/bin/java.c +++ b/jdk/src/share/bin/java.c @@ -53,6 +53,8 @@ #include "java.h" +#include + /* * A NOTE TO DEVELOPERS: For performance reasons it is important that * the program image remain relatively small until after SelectVersion @@ -167,6 +169,26 @@ static jlong threadStackSize = 0; /* stack size of the new thread */ static jlong maxHeapSize = 0; /* max heap size */ static jlong initialHeapSize = 0; /* inital heap size */ +static jlong timestamps[256]; +static char* descriptors[256]; +static int ts_index = 0; + +static void stamp(char* info) { + struct timespec tp; + clock_gettime(CLOCK_MONOTONIC, &tp); + timestamps[ts_index] = ((jlong)tp.tv_sec) * (1000 * 1000 * 1000) + tp.tv_nsec; + descriptors[ts_index++] = info; +} + +static void report_times() { + printf("[0] %s\n", descriptors[0]); + int i; + for (i = 1; i < ts_index; i++) { + jlong elapsed = timestamps[i] - timestamps[i-1]; + printf("[%d] elapsed us: %.3g - Next: %s\n", i, (elapsed/1000.0), descriptors[i]); + } +} + /* * Entry point. */ @@ -184,6 +206,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ jint ergo /* ergonomics class policy */ ) { + stamp("Entered JLI_Launch"); int mode = LM_UNKNOWN; char *what = NULL; char *cpath = 0; @@ -203,6 +226,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ _wc_enabled = cpwildcard; _ergo_policy = ergo; +stamp("InitLauncher"); InitLauncher(javaw); DumpState(); if (JLI_IsTraceLauncher()) { @@ -231,8 +255,9 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ * (Note: This side effect has been disabled. See comment on * bugid 5030265 below.) */ +stamp("SelectVersion"); SelectVersion(argc, argv, &main_class); - +stamp("CreateExecutionEnvironment"); CreateExecutionEnvironment(&argc, &argv, jrepath, sizeof(jrepath), jvmpath, sizeof(jvmpath), @@ -244,11 +269,11 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ if (JLI_IsTraceLauncher()) { start = CounterGet(); } - +stamp("LoadJavaVM"); if (!LoadJavaVM(jvmpath, &ifn)) { return(6); } - +stamp("Arg processing"); if (JLI_IsTraceLauncher()) { end = CounterGet(); } @@ -295,8 +320,10 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ /* set the -Dsun.java.launcher.* platform properties */ SetJavaLauncherPlatformProps(); - - return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret); +stamp("JVMInit"); + int res = JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret); +stamp("initial thread DONE"); + return res; } /* * Always detach the main thread so that it appears to have ended when @@ -348,6 +375,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ int JNICALL JavaMain(void * _args) { +stamp("JavaMain"); JavaMainArgs *args = (JavaMainArgs *)_args; int argc = args->argc; char **argv = args->argv; @@ -363,11 +391,12 @@ JavaMain(void * _args) jobjectArray mainArgs; int ret = 0; jlong start, end; - +stamp("RegisterThread"); RegisterThread(); /* Initialize the virtual machine */ start = CounterGet(); +stamp("InitializeJVM"); if (!InitializeJVM(&vm, &env, &ifn)) { JLI_ReportErrorMessage(JVM_ERROR1); exit(1); @@ -436,6 +465,7 @@ JavaMain(void * _args) * This method also correctly handles launching existing JavaFX * applications that may or may not have a Main-Class manifest entry. */ +stamp("LoadMainClass"); mainClass = LoadMainClass(env, mode, what); CHECK_EXCEPTION_NULL_LEAVE(mainClass); /* @@ -444,6 +474,7 @@ JavaMain(void * _args) * applications own main class but rather a helper class. To keep things * consistent in the UI we need to track and report the application main class. */ +stamp("GetApplicationClass"); appClass = GetApplicationClass(env); NULL_CHECK_RETURN_VALUE(appClass, -1); /* @@ -453,6 +484,7 @@ JavaMain(void * _args) * instead of mainClass as that may be a launcher or helper class instead * of the application class. */ +stamp("PostJVMInit"); PostJVMInit(env, appClass, vm); /* * The LoadMainClass not only loads the main class, it will also ensure @@ -460,17 +492,20 @@ JavaMain(void * _args) * is not required. The main method is invoked here so that extraneous java * stacks are not in the application stack trace. */ +stamp("Get main method"); mainID = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V"); CHECK_EXCEPTION_NULL_LEAVE(mainID); - +stamp("CreateApplicationArgs"); /* Build platform specific argument array */ mainArgs = CreateApplicationArgs(env, argv, argc); CHECK_EXCEPTION_NULL_LEAVE(mainArgs); /* Invoke main method. */ +stamp("Invoke main method"); (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); - +stamp("main complete"); +report_times(); /* * The launcher's exit code (in the absence of calls to * System.exit) will be non-zero if main threw an exception. @@ -1875,6 +1910,7 @@ ContinueInNewThread(InvocationFunctions* ifn, jlong threadStackSize, int argc, char **argv, int mode, char *what, int ret) { +stamp("ContinueInNewThread"); /* * If user doesn't specify stack size, check if VM has a preference. @@ -1900,7 +1936,7 @@ ContinueInNewThread(InvocationFunctions* ifn, jlong threadStackSize, args.mode = mode; args.what = what; args.ifn = *ifn; - +stamp("ContinueInNewThread0"); rslt = ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args); /* If the caller has deemed there is an error we * simply return that, otherwise we return the value of diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java index 1394a4c38ed..47c28540f24 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java @@ -33,6 +33,7 @@ import java.security.*; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; +import java.util.concurrent.locks.ReentrantLock; public class ThrowingTasks { static final Random rnd = new Random(); @@ -156,6 +157,7 @@ public class ThrowingTasks { } static class CheckingExecutor extends ThreadPoolExecutor { + private final ReentrantLock lock = new ReentrantLock(); CheckingExecutor() { super(10, 10, 1L, TimeUnit.HOURS, @@ -163,10 +165,20 @@ public class ThrowingTasks { tf); } @Override protected void beforeExecute(Thread t, Runnable r) { - allStarted.countDown(); - if (allStarted.getCount() < getCorePoolSize()) + final boolean lessThanCorePoolSize; + // Add a lock to sync allStarted.countDown() and + // allStarted.getCount() < getCorePoolSize() + lock.lock(); + try { + allStarted.countDown(); + lessThanCorePoolSize = allStarted.getCount() < getCorePoolSize(); + } finally { + lock.unlock(); + } + if (lessThanCorePoolSize) { try { allContinue.await(); } catch (InterruptedException x) { unexpected(x); } + } beforeExecuteCount.getAndIncrement(); check(! isTerminated()); ((Flaky)r).beforeExecute.run(); From c43c119a472b40b5a990a7e2135b3cfb637c6ab4 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Mon, 4 Nov 2013 07:39:48 -0500 Subject: [PATCH 06/74] 8027755: Anti-delta incorrect push for 8025198 Reviewed-by: alanb --- jdk/makefiles/CompileLaunchers.gmk | 2 +- jdk/makefiles/lib/CoreLibraries.gmk | 2 +- jdk/src/share/bin/java.c | 54 +++++------------------------ 3 files changed, 11 insertions(+), 47 deletions(-) diff --git a/jdk/makefiles/CompileLaunchers.gmk b/jdk/makefiles/CompileLaunchers.gmk index 2de3900acd0..af5b3583758 100644 --- a/jdk/makefiles/CompileLaunchers.gmk +++ b/jdk/makefiles/CompileLaunchers.gmk @@ -154,7 +154,7 @@ define SetupLauncher $(ORIGIN_ARG) \ $$($1_LDFLAGS), \ LDFLAGS_macosx := $(call SET_SHARED_LIBRARY_NAME,$1), \ - LDFLAGS_linux := -lpthread -lrt \ + LDFLAGS_linux := -lpthread \ $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \ LDFLAGS_solaris := $$($1_LDFLAGS_solaris) \ $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \ diff --git a/jdk/makefiles/lib/CoreLibraries.gmk b/jdk/makefiles/lib/CoreLibraries.gmk index a631cf80cde..29c1d5fc08a 100644 --- a/jdk/makefiles/lib/CoreLibraries.gmk +++ b/jdk/makefiles/lib/CoreLibraries.gmk @@ -414,7 +414,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJLI, \ LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \ LDFLAGS_macosx := -framework Cocoa -framework Security -framework ApplicationServices, \ LDFLAGS_SUFFIX_solaris := $(LIBZ) $(LIBDL) -lc, \ - LDFLAGS_SUFFIX_linux := $(LIBZ) $(LIBDL) -lc -lpthread -lrt, \ + LDFLAGS_SUFFIX_linux := $(LIBZ) $(LIBDL) -lc -lpthread, \ LDFLAGS_SUFFIX_macosx := $(LIBZ), \ LDFLAGS_SUFFIX_windows := \ -export:JLI_Launch \ diff --git a/jdk/src/share/bin/java.c b/jdk/src/share/bin/java.c index 9d1b2bf0209..73c532676b3 100644 --- a/jdk/src/share/bin/java.c +++ b/jdk/src/share/bin/java.c @@ -53,8 +53,6 @@ #include "java.h" -#include - /* * A NOTE TO DEVELOPERS: For performance reasons it is important that * the program image remain relatively small until after SelectVersion @@ -169,26 +167,6 @@ static jlong threadStackSize = 0; /* stack size of the new thread */ static jlong maxHeapSize = 0; /* max heap size */ static jlong initialHeapSize = 0; /* inital heap size */ -static jlong timestamps[256]; -static char* descriptors[256]; -static int ts_index = 0; - -static void stamp(char* info) { - struct timespec tp; - clock_gettime(CLOCK_MONOTONIC, &tp); - timestamps[ts_index] = ((jlong)tp.tv_sec) * (1000 * 1000 * 1000) + tp.tv_nsec; - descriptors[ts_index++] = info; -} - -static void report_times() { - printf("[0] %s\n", descriptors[0]); - int i; - for (i = 1; i < ts_index; i++) { - jlong elapsed = timestamps[i] - timestamps[i-1]; - printf("[%d] elapsed us: %.3g - Next: %s\n", i, (elapsed/1000.0), descriptors[i]); - } -} - /* * Entry point. */ @@ -206,7 +184,6 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ jint ergo /* ergonomics class policy */ ) { - stamp("Entered JLI_Launch"); int mode = LM_UNKNOWN; char *what = NULL; char *cpath = 0; @@ -226,7 +203,6 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */ _wc_enabled = cpwildcard; _ergo_policy = ergo; -stamp("InitLauncher"); InitLauncher(javaw); DumpState(); if (JLI_IsTraceLauncher()) { @@ -255,9 +231,8 @@ stamp("InitLauncher"); * (Note: This side effect has been disabled. See comment on * bugid 5030265 below.) */ -stamp("SelectVersion"); SelectVersion(argc, argv, &main_class); -stamp("CreateExecutionEnvironment"); + CreateExecutionEnvironment(&argc, &argv, jrepath, sizeof(jrepath), jvmpath, sizeof(jvmpath), @@ -269,11 +244,11 @@ stamp("CreateExecutionEnvironment"); if (JLI_IsTraceLauncher()) { start = CounterGet(); } -stamp("LoadJavaVM"); + if (!LoadJavaVM(jvmpath, &ifn)) { return(6); } -stamp("Arg processing"); + if (JLI_IsTraceLauncher()) { end = CounterGet(); } @@ -320,10 +295,8 @@ stamp("Arg processing"); /* set the -Dsun.java.launcher.* platform properties */ SetJavaLauncherPlatformProps(); -stamp("JVMInit"); - int res = JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret); -stamp("initial thread DONE"); - return res; + + return JVMInit(&ifn, threadStackSize, argc, argv, mode, what, ret); } /* * Always detach the main thread so that it appears to have ended when @@ -375,7 +348,6 @@ stamp("initial thread DONE"); int JNICALL JavaMain(void * _args) { -stamp("JavaMain"); JavaMainArgs *args = (JavaMainArgs *)_args; int argc = args->argc; char **argv = args->argv; @@ -391,12 +363,11 @@ stamp("JavaMain"); jobjectArray mainArgs; int ret = 0; jlong start, end; -stamp("RegisterThread"); + RegisterThread(); /* Initialize the virtual machine */ start = CounterGet(); -stamp("InitializeJVM"); if (!InitializeJVM(&vm, &env, &ifn)) { JLI_ReportErrorMessage(JVM_ERROR1); exit(1); @@ -465,7 +436,6 @@ stamp("InitializeJVM"); * This method also correctly handles launching existing JavaFX * applications that may or may not have a Main-Class manifest entry. */ -stamp("LoadMainClass"); mainClass = LoadMainClass(env, mode, what); CHECK_EXCEPTION_NULL_LEAVE(mainClass); /* @@ -474,7 +444,6 @@ stamp("LoadMainClass"); * applications own main class but rather a helper class. To keep things * consistent in the UI we need to track and report the application main class. */ -stamp("GetApplicationClass"); appClass = GetApplicationClass(env); NULL_CHECK_RETURN_VALUE(appClass, -1); /* @@ -484,7 +453,6 @@ stamp("GetApplicationClass"); * instead of mainClass as that may be a launcher or helper class instead * of the application class. */ -stamp("PostJVMInit"); PostJVMInit(env, appClass, vm); /* * The LoadMainClass not only loads the main class, it will also ensure @@ -492,20 +460,17 @@ stamp("PostJVMInit"); * is not required. The main method is invoked here so that extraneous java * stacks are not in the application stack trace. */ -stamp("Get main method"); mainID = (*env)->GetStaticMethodID(env, mainClass, "main", "([Ljava/lang/String;)V"); CHECK_EXCEPTION_NULL_LEAVE(mainID); -stamp("CreateApplicationArgs"); + /* Build platform specific argument array */ mainArgs = CreateApplicationArgs(env, argv, argc); CHECK_EXCEPTION_NULL_LEAVE(mainArgs); /* Invoke main method. */ -stamp("Invoke main method"); (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); -stamp("main complete"); -report_times(); + /* * The launcher's exit code (in the absence of calls to * System.exit) will be non-zero if main threw an exception. @@ -1910,7 +1875,6 @@ ContinueInNewThread(InvocationFunctions* ifn, jlong threadStackSize, int argc, char **argv, int mode, char *what, int ret) { -stamp("ContinueInNewThread"); /* * If user doesn't specify stack size, check if VM has a preference. @@ -1936,7 +1900,7 @@ stamp("ContinueInNewThread"); args.mode = mode; args.what = what; args.ifn = *ifn; -stamp("ContinueInNewThread0"); + rslt = ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args); /* If the caller has deemed there is an error we * simply return that, otherwise we return the value of From 8c97f82aae76084c8c6f1d57ef56605907caa296 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Mon, 4 Nov 2013 08:05:02 -0800 Subject: [PATCH 07/74] 8027625: test/java/math/BigInteger/ExtremeShiftingTests.java needs @run tag to specify heap size Add @run tag to specify heap size Reviewed-by: alanb, dxu --- jdk/test/java/math/BigInteger/ExtremeShiftingTests.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/java/math/BigInteger/ExtremeShiftingTests.java b/jdk/test/java/math/BigInteger/ExtremeShiftingTests.java index 4c39a6097fd..5ddc07e887c 100644 --- a/jdk/test/java/math/BigInteger/ExtremeShiftingTests.java +++ b/jdk/test/java/math/BigInteger/ExtremeShiftingTests.java @@ -25,6 +25,7 @@ * @test * @bug 6371401 * @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE + * @run main/othervm -Xmx512m ExtremeShiftingTests * @author Joseph D. Darcy */ import java.math.BigInteger; From 2d8325d24451e286631d2d2fbcd2696756ebc924 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Mon, 4 Nov 2013 17:47:59 +0000 Subject: [PATCH 08/74] 8027687: The constructors of URLPermission class do not behave as described in javad Reviewed-by: chegar, mduigou --- .../share/classes/java/net/HostPortrange.java | 36 +++++++++++++++++-- .../share/classes/java/net/URLPermission.java | 5 ++- .../net/URLPermission/URLPermissionTest.java | 13 ++++++- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/classes/java/net/HostPortrange.java b/jdk/src/share/classes/java/net/HostPortrange.java index fc5e3d98a20..3c924d8bfc0 100644 --- a/jdk/src/share/classes/java/net/HostPortrange.java +++ b/jdk/src/share/classes/java/net/HostPortrange.java @@ -114,7 +114,7 @@ class HostPortrange { if (hoststr.equals("*")) { hoststr = ""; } else if (hoststr.startsWith("*.")) { - hoststr = hoststr.substring(1).toLowerCase(); // leave the '.' ? + hoststr = toLowerCase(hoststr.substring(1)); } else { throw new IllegalArgumentException("invalid host wildcard specification"); } @@ -147,7 +147,7 @@ class HostPortrange { hoststr = sb.toString(); } else { // regular domain name - hoststr = hoststr.toLowerCase(); + hoststr = toLowerCase(hoststr); } } } @@ -161,6 +161,38 @@ class HostPortrange { } } + static final int CASE_DIFF = 'A' - 'a'; + + /** + * Convert to lower case, and check that all chars are ascii + * alphanumeric, '-' or '.' only. + */ + static String toLowerCase(String s) { + int len = s.length(); + StringBuilder sb = null; + + for (int i=0; i= 'a' && c <= 'z') || (c == '.')) { + if (sb != null) + sb.append(c); + } else if ((c >= '0' && c <= '9') || (c == '-')) { + if (sb != null) + sb.append(c); + } else if (c >= 'A' && c <= 'Z') { + if (sb == null) { + sb = new StringBuilder(len); + sb.append(s, 0, i); + } + sb.append((char)(c - CASE_DIFF)); + } else { + throw new IllegalArgumentException("Invalid characters in hostname"); + } + } + return sb == null ? s : sb.toString(); + } + + public boolean literal() { return literal; } diff --git a/jdk/src/share/classes/java/net/URLPermission.java b/jdk/src/share/classes/java/net/URLPermission.java index 7ad56a1c20f..13472a9e5ab 100644 --- a/jdk/src/share/classes/java/net/URLPermission.java +++ b/jdk/src/share/classes/java/net/URLPermission.java @@ -426,7 +426,10 @@ public final class URLPermission extends Permission { this.ssp = url.substring(delim + 1); if (!ssp.startsWith("//")) { - this.authority = new Authority(scheme, ssp.toLowerCase()); + if (!ssp.equals("*")) { + throw new IllegalArgumentException("invalid URL string"); + } + this.authority = new Authority(scheme, "*"); return; } String authpath = ssp.substring(2); diff --git a/jdk/test/java/net/URLPermission/URLPermissionTest.java b/jdk/test/java/net/URLPermission/URLPermissionTest.java index 3bf862b6dc9..948e9dabb13 100644 --- a/jdk/test/java/net/URLPermission/URLPermissionTest.java +++ b/jdk/test/java/net/URLPermission/URLPermissionTest.java @@ -186,6 +186,14 @@ public class URLPermissionTest { imtest("http:*", "https://www.foo.com/a/b/c", false), imtest("http:*", "http://www.foo.com/a/b/c", true), imtest("http:*", "http://foo/bar", true), + imtest("http://WWW.foO.cOM/a/b/*", "http://wwW.foo.com/a/b/c", true), + imtest("http://wWw.fOo.cOm/a/b/*", "http://Www.foo.com/a/b/*", true), + imtest("http://www.FOO.com/", "http://www.foo.COM/", true), + imtest("http://66ww-w.F-O012O.com/", "http://66ww-w.f-o012o.COM/",true), + imtest("http://xn--ire-9la.com/", "http://xn--ire-9la.COM/", true), + imtest("http://x/", "http://X/", true), + imtest("http://x/", "http://x/", true), + imtest("http://X/", "http://X/", true), imtest("http://foo/bar", "https://foo/bar", false) }; @@ -194,9 +202,12 @@ public class URLPermissionTest { static Test[] exceptionTests = { extest("http://1.2.3.4.5/a/b/c"), extest("http://www.*.com"), - //extest("http://www.foo.com:1-X"), extest("http://[foo.com]:99"), extest("http://[fec0::X]:99"), + extest("http:\\www.foo.com"), + extest("http://w_09ww.foo.com"), + extest("http://w&09ww.foo.com/p"), + extest("http://www+foo.com"), extest("http:") }; From ee1006e3bd0f49054996f387b8ec20361716fa2d Mon Sep 17 00:00:00 2001 From: Robert Field Date: Mon, 4 Nov 2013 10:12:18 -0800 Subject: [PATCH 09/74] 7194897: JSR 292: Cannot create more than 16 instances of an anonymous class 8027681: Lambda serialization fails once reflection proxy generation kicks in Co-authored-by: Joel Borggren-Franck Co-authored-by: Brian Goetz Reviewed-by: ksrini, briangoetz, jfranck --- .../NativeConstructorAccessorImpl.java | 9 ++- .../sun/reflect/NativeMethodAccessorImpl.java | 9 ++- .../classes/sun/reflect/misc/ReflectUtil.java | 11 +++- .../lambda/RepetitiveLambdaSerialization.java | 53 ++++++++++++++++ .../lang/invoke/SerializedLambdaTest.java | 12 ++-- .../ManyNewInstanceAnonTest.java | 62 +++++++++++++++++++ 6 files changed, 147 insertions(+), 9 deletions(-) create mode 100644 jdk/test/java/lang/invoke/lambda/RepetitiveLambdaSerialization.java create mode 100644 jdk/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java diff --git a/jdk/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java b/jdk/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java index 4f91ddc4460..d56c3caab08 100644 --- a/jdk/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java +++ b/jdk/src/share/classes/sun/reflect/NativeConstructorAccessorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package sun.reflect; import java.lang.reflect.*; +import sun.reflect.misc.ReflectUtil; /** Used only for the first few invocations of a Constructor; afterward, switches to bytecode-based implementation */ @@ -44,7 +45,11 @@ class NativeConstructorAccessorImpl extends ConstructorAccessorImpl { IllegalArgumentException, InvocationTargetException { - if (++numInvocations > ReflectionFactory.inflationThreshold()) { + // We can't inflate a constructor belonging to a vm-anonymous class + // because that kind of class can't be referred to by name, hence can't + // be found from the generated bytecode. + if (++numInvocations > ReflectionFactory.inflationThreshold() + && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) { ConstructorAccessorImpl acc = (ConstructorAccessorImpl) new MethodAccessorGenerator(). generateConstructor(c.getDeclaringClass(), diff --git a/jdk/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java b/jdk/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java index 93f186b7b49..b1d39e7c965 100644 --- a/jdk/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java +++ b/jdk/src/share/classes/sun/reflect/NativeMethodAccessorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package sun.reflect; import java.lang.reflect.*; +import sun.reflect.misc.ReflectUtil; /** Used only for the first few invocations of a Method; afterward, switches to bytecode-based implementation */ @@ -42,7 +43,11 @@ class NativeMethodAccessorImpl extends MethodAccessorImpl { public Object invoke(Object obj, Object[] args) throws IllegalArgumentException, InvocationTargetException { - if (++numInvocations > ReflectionFactory.inflationThreshold()) { + // We can't inflate methods belonging to vm-anonymous classes because + // that kind of class can't be referred to by name, hence can't be + // found from the generated bytecode. + if (++numInvocations > ReflectionFactory.inflationThreshold() + && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) { MethodAccessorImpl acc = (MethodAccessorImpl) new MethodAccessorGenerator(). generateMethod(method.getDeclaringClass(), diff --git a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java index 1f871e8de02..4316d422c39 100644 --- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java +++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -298,4 +298,13 @@ public final class ReflectUtil { } return false; } + + /** + * Checks if {@code Class cls} is a VM-anonymous class + * as defined by {@link sun.misc.Unsafe#defineAnonymousClass} + * (not to be confused with a Java Language anonymous inner class). + */ + public static boolean isVMAnonymousClass(Class cls) { + return cls.getSimpleName().contains("/"); + } } diff --git a/jdk/test/java/lang/invoke/lambda/RepetitiveLambdaSerialization.java b/jdk/test/java/lang/invoke/lambda/RepetitiveLambdaSerialization.java new file mode 100644 index 00000000000..5c57615a307 --- /dev/null +++ b/jdk/test/java/lang/invoke/lambda/RepetitiveLambdaSerialization.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8027681 + * @summary Lambda serialization fails once reflection proxy generation kicks in + * @author Robert Field + * @run main/othervm RepetitiveLambdaSerialization + */ + +import java.io.*; + +public class RepetitiveLambdaSerialization { + + static final int REPS = 20; + + public static void main(String[] args) throws Exception { + LSI ls = z -> "[" + z + "]"; + for (int i = 0; i < REPS; ++i) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutput out = new ObjectOutputStream(baos); + out.writeObject(ls); + out.flush(); + out.close(); + } + System.out.println("Passed."); + } +} + +interface LSI extends Serializable { + String convert(String x); +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java index 8f01dada86f..fdbd689ad36 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/lang/invoke/SerializedLambdaTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,14 +56,18 @@ import static org.testng.Assert.fail; */ @Test public class SerializedLambdaTest { + public static final int REPS = 50; + @SuppressWarnings("unchecked") private void assertSerial(T p, Consumer asserter) throws IOException, ClassNotFoundException { asserter.accept(p); - byte[] bytes = serialize(p); - assertTrue(bytes.length > 0); + for (int i=0; i 0); - asserter.accept((T) deserialize(bytes)); + asserter.accept((T) deserialize(bytes)); + } } private void assertNotSerial(Predicate p, Consumer> asserter) diff --git a/jdk/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java b/jdk/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java new file mode 100644 index 00000000000..b931b8a65f8 --- /dev/null +++ b/jdk/test/sun/reflect/AnonymousNewInstance/ManyNewInstanceAnonTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7194897 + * @summary JSR 292: Cannot create more than 16 instances of an anonymous class + * @author Robert Field + * @library /lib/testlibrary + * @compile -XDignore.symbol.file ManyNewInstanceAnonTest.java + * @run main ClassFileInstaller ManyNewInstanceAnonTest + * @run main/othervm -Xbootclasspath/a:. -Xverify:all ManyNewInstanceAnonTest + */ +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import sun.misc.Unsafe; + +public class ManyNewInstanceAnonTest { + + static final int REPS = 20; + static final Class klass = ManyNewInstanceAnonTest.class; + + public static void main(String[] args) throws Exception { + Class c = Unsafe.getUnsafe().defineAnonymousClass(klass, readClassFile(), null); + for (int i = 0; i < REPS; ++i) { + System.out.printf("%d: %s\n", i, c.newInstance()); + } + System.out.println("Passed."); + } + + private static byte[] readClassFile() throws Exception { + try (InputStream in = klass.getResourceAsStream(klass.getSimpleName() + ".class"); + ByteArrayOutputStream out = new ByteArrayOutputStream()) + { + int b; + while ((b = in.read()) != -1) { + out.write(b); + } + return out.toByteArray(); + } + } +} From 79b1f94594b1743ed2f45251b63123c4ae60f1ba Mon Sep 17 00:00:00 2001 From: Andreas Lundblad Date: Mon, 4 Nov 2013 15:21:47 +0100 Subject: [PATCH 10/74] 8016725: TEST_BUG: java/lang/reflect/Method/DefaultMethodModeling.java failing intermittently Moved DefaultMethodModeling.java to its own directory to avoid conflicts with Equals.java. Reviewed-by: darcy --- .../Method/{ => defaultMethodModeling}/DefaultMethodModeling.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename jdk/test/java/lang/reflect/Method/{ => defaultMethodModeling}/DefaultMethodModeling.java (100%) diff --git a/jdk/test/java/lang/reflect/Method/DefaultMethodModeling.java b/jdk/test/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java similarity index 100% rename from jdk/test/java/lang/reflect/Method/DefaultMethodModeling.java rename to jdk/test/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java From 3fdca184336549a0dcc7a20a96348bcbd61a72aa Mon Sep 17 00:00:00 2001 From: Dan Xu Date: Mon, 4 Nov 2013 15:48:08 -0800 Subject: [PATCH 11/74] 8027612: java/io/File/MaxPathLength.java fails intermittently in the clean-up stage Reviewed-by: chegar --- jdk/test/java/io/File/MaxPathLength.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/io/File/MaxPathLength.java b/jdk/test/java/io/File/MaxPathLength.java index 9fd6183f36d..cdda0471446 100644 --- a/jdk/test/java/io/File/MaxPathLength.java +++ b/jdk/test/java/io/File/MaxPathLength.java @@ -28,6 +28,8 @@ import java.io.*; import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.DirectoryNotEmptyException; public class MaxPathLength { private static String sep = File.separator; @@ -182,7 +184,18 @@ public class MaxPathLength { } finally { // Clean up for (int i = 0; i < max; i++) { - Files.deleteIfExists((new File(created[i])).toPath()); + Path p = (new File(created[i])).toPath(); + try { + Files.deleteIfExists(p); + // Test if the file is really deleted and wait for 1 second at most + for (int j = 0; j < 10 && Files.exists(p); j++) { + Thread.sleep(100); + } + } catch (DirectoryNotEmptyException ex) { + // Give up the clean-up, let jtreg handle it. + System.err.println("Dir, " + p + ", is not empty"); + break; + } } } } From fe6f3e2439db3d75d114c98cf661e8ecb32824fc Mon Sep 17 00:00:00 2001 From: Paul Sandoz Date: Tue, 5 Nov 2013 12:08:12 +0100 Subject: [PATCH 12/74] 8027712: DistinctOpTest fails for unordered test Reviewed-by: henryjen, alanb --- .../openjdk/tests/java/util/stream/DistinctOpTest.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java index 7d26925a1f2..69432cfedf6 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java @@ -54,10 +54,14 @@ public class DistinctOpTest extends OpTestCase { // These tests should short-circuit, otherwise will fail with a time-out // or an OOME - Integer one = Stream.iterate(1, i -> i + 1).unordered().parallel().distinct().findAny().get(); - assertEquals(one.intValue(), 1); + // Note that since the streams are unordered and any element is requested + // (a non-deterministic process) the only assertion that can be made is + // that an element should be found - Optional oi = ThreadLocalRandom.current().ints().boxed().parallel().distinct().findAny(); + Optional oi = Stream.iterate(1, i -> i + 1).unordered().parallel().distinct().findAny(); + assertTrue(oi.isPresent()); + + oi = ThreadLocalRandom.current().ints().boxed().parallel().distinct().findAny(); assertTrue(oi.isPresent()); } From 33be168ccb7c6d033fce9cbe541f4c118811aa46 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Tue, 5 Nov 2013 11:18:20 -0800 Subject: [PATCH 13/74] 8027860: [TEST_BUG] File not closed in javax/xml/jaxp/parsers/8022548/XOMParserTest.java Reviewed-by: alanb --- .../jaxp/parsers/8022548/XOMParserTest.java | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/jdk/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java b/jdk/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java index ba12d0ddc86..15915d04912 100644 --- a/jdk/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java +++ b/jdk/test/javax/xml/jaxp/parsers/8022548/XOMParserTest.java @@ -22,7 +22,8 @@ */ /** - * @test @bug 8022548 + * @test + * @bug 8022548 * @summary test that a parser can use DTDConfiguration * @run main XOMParserTest */ @@ -60,30 +61,27 @@ public class XOMParserTest extends TestBase { } public final void testTransform() { + String inFilename = filePath + "/JDK8022548.xml"; + String xslFilename = filePath + "/JDK8022548.xsl"; + String outFilename = "JDK8022548.out"; - try { + try (InputStream xslInput = new FileInputStream(xslFilename); + InputStream xmlInput = new FileInputStream(inFilename); + OutputStream out = new FileOutputStream(outFilename); + ) { - String inFilename = filePath + "/JDK8022548.xml"; - String xslFilename = filePath + "/JDK8022548.xsl"; - String outFilename = "JDK8022548.out"; StringWriter sw = new StringWriter(); // Create transformer factory TransformerFactory factory = TransformerFactory.newInstance(); - // set the translet name -// factory.setAttribute("translet-name", "myTranslet"); - - // set the destination directory -// factory.setAttribute("destination-directory", "c:\\temp"); -// factory.setAttribute("generate-translet", Boolean.TRUE); // Use the factory to create a template containing the xsl file - Templates template = factory.newTemplates(new StreamSource(new FileInputStream(xslFilename))); + Templates template = factory.newTemplates(new StreamSource(xslInput)); // Use the template to create a transformer Transformer xformer = template.newTransformer(); // Prepare the input and output files - Source source = new StreamSource(new FileInputStream(inFilename)); - Result result = new StreamResult(new FileOutputStream(outFilename)); + Source source = new StreamSource(xmlInput); + Result result = new StreamResult(outFilename); //Result result = new StreamResult(sw); // Apply the xsl file to the source file and write the result to the output file xformer.transform(source, result); From 1b7f902c51a23227550663bbebbe4e9a0591d56b Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Tue, 5 Nov 2013 17:33:26 -0800 Subject: [PATCH 14/74] 8022208: Intermittent test failures in java/lang/Thread/ThreadStateTest.java 6944188: ThreadMXBean/ThreadStateTest.java fails intermittently Reviewed-by: dholmes, chegar --- .../lang/Thread/ThreadStateController.java | 340 ++++++++++++++ .../java/lang/Thread/ThreadStateTest.java | 304 ++----------- .../ThreadMXBean/ThreadMXBeanStateTest.java | 230 ++++++++++ .../ThreadMXBean/ThreadStateTest.java | 424 ------------------ 4 files changed, 597 insertions(+), 701 deletions(-) create mode 100644 jdk/test/java/lang/Thread/ThreadStateController.java create mode 100644 jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java delete mode 100644 jdk/test/java/lang/management/ThreadMXBean/ThreadStateTest.java diff --git a/jdk/test/java/lang/Thread/ThreadStateController.java b/jdk/test/java/lang/Thread/ThreadStateController.java new file mode 100644 index 00000000000..2d876b0ec41 --- /dev/null +++ b/jdk/test/java/lang/Thread/ThreadStateController.java @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.concurrent.Phaser; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.LockSupport; + +/** + * ThreadStateController allows a thread to request this thread to transition + * to a specific thread state. The {@linkplain #transitionTo request} is + * a blocking call that the calling thread will wait until this thread is about + * going to the new state. Only one request of state transition at a time + * is supported (the Phaser expects only parties of 2 to arrive and advance + * to next phase). + */ +public class ThreadStateController extends Thread { + // used to achieve waiting states + private final Object lock; + public ThreadStateController(String name, Object lock) { + super(name); + this.lock = lock; + } + + public void checkThreadState(Thread.State expected) { + // maximum number of retries when checking for thread state. + final int MAX_RETRY = 500; + + // wait for the thread to transition to the expected state. + // There is a small window between the thread checking the state + // and the thread actual entering that state. + Thread.State state; + int retryCount=0; + while ((state = getState()) != expected && retryCount < MAX_RETRY) { + pause(10); + retryCount++; + } + + if (state == null) { + throw new RuntimeException(getName() + " expected to have " + + expected + " but got null."); + } + + if (state != expected) { + throw new RuntimeException(String.format("%s expected in %s state but got %s " + + "(iterations %d interrupted %d)%n", + getName(), expected, state, iterations.get(), interrupted.get())); + } + } + + public static void pause(long ms) { + try { + Thread.sleep(ms); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + // Phaser to sync between the main thread putting + // this thread into various states + private final Phaser phaser = new Phaser(2); + private volatile int newState = S_RUNNABLE; + private volatile int state = 0; + private boolean done = false; + + private static final int S_RUNNABLE = 1; + private static final int S_BLOCKED = 2; + private static final int S_WAITING = 3; + private static final int S_TIMED_WAITING = 4; + private static final int S_PARKED = 5; + private static final int S_TIMED_PARKED = 6; + private static final int S_SLEEPING = 7; + private static final int S_TERMINATE = 8; + + // for debugging + private AtomicInteger iterations = new AtomicInteger(); + private AtomicInteger interrupted = new AtomicInteger(); + public void run() { + // this thread has started + while (!done) { + // state transition + int nextState = state; + if (newState != state) { + nextState = newState; + iterations.set(0); + interrupted.set(0); + } + iterations.incrementAndGet(); + switch (nextState) { + case S_RUNNABLE: { + stateChange(nextState); + double sum = 0; + for (int i = 0; i < 1000; i++) { + double r = Math.random(); + double x = Math.pow(3, r); + sum += x - r; + } + break; + } + case S_BLOCKED: { + System.out.format("%d: %s is going to block (interations %d)%n", + getId(), getName(), iterations.get()); + stateChange(nextState); + // going to block on lock + synchronized (lock) { + System.out.format("%d: %s acquired the lock (interations %d)%n", + getId(), getName(), iterations.get()); + try { + // this thread has escaped the BLOCKED state + // release the lock and a short wait before continue + lock.wait(10); + } catch (InterruptedException e) { + // ignore + interrupted.incrementAndGet(); + } + } + break; + } + case S_WAITING: { + synchronized (lock) { + System.out.format("%d: %s is going to waiting (interations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); + try { + stateChange(nextState); + lock.wait(); + System.out.format("%d: %s wakes up from waiting (interations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); + } catch (InterruptedException e) { + // ignore + interrupted.incrementAndGet(); + } + } + break; + } + case S_TIMED_WAITING: { + synchronized (lock) { + System.out.format("%d: %s is going to timed waiting (interations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); + try { + stateChange(nextState); + lock.wait(10000); + System.out.format("%d: %s wakes up from timed waiting (interations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); + } catch (InterruptedException e) { + // ignore + interrupted.incrementAndGet(); + } + } + break; + } + case S_PARKED: { + System.out.format("%d: %s is going to park (interations %d)%n", + getId(), getName(), iterations.get()); + stateChange(nextState); + LockSupport.park(); + break; + } + case S_TIMED_PARKED: { + System.out.format("%d: %s is going to timed park (interations %d)%n", + getId(), getName(), iterations.get()); + long deadline = System.currentTimeMillis() + 10000*1000; + stateChange(nextState); + LockSupport.parkUntil(deadline); + break; + } + case S_SLEEPING: { + System.out.format("%d: %s is going to sleep (interations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); + try { + stateChange(nextState); + Thread.sleep(1000000); + } catch (InterruptedException e) { + // finish sleeping + interrupted.incrementAndGet(); + } + break; + } + case S_TERMINATE: { + done = true; + stateChange(nextState); + break; + } + default: + break; + } + } + } + + /** + * Change the state if it matches newState. + */ + private void stateChange(int nextState) { + // no state change + if (state == nextState) + return; + + // transition to the new state + if (newState == nextState) { + state = nextState; + phaser.arrive(); + System.out.format("%d: state change: %s %s%n", + getId(), toStateName(nextState), phaserToString(phaser)); + return; + } + + // should never reach here + throw new RuntimeException("current " + state + " next " + nextState + + " new state " + newState); + } + + /** + * Blocks until this thread transitions to the given state + */ + public void transitionTo(Thread.State tstate) throws InterruptedException { + switch (tstate) { + case RUNNABLE: + nextState(S_RUNNABLE); + break; + case BLOCKED: + nextState(S_BLOCKED); + break; + case WAITING: + nextState(S_WAITING); + break; + case TIMED_WAITING: + nextState(S_TIMED_WAITING); + break; + case TERMINATED: + nextState(S_TERMINATE); + break; + default: + break; + } + } + + /** + * Blocks until this thread transitions to sleeping + */ + public void transitionToSleep() throws InterruptedException { + nextState(S_SLEEPING); + } + + /** + * Blocks until this thread transitions to park or timed park + */ + public void transitionToPark(boolean timed) throws InterruptedException { + nextState(timed ? S_TIMED_PARKED : S_PARKED); + } + + private void nextState(int s) throws InterruptedException { + final long id = Thread.currentThread().getId(); + System.out.format("%d: wait until the thread transitions to %s %s%n", + id, toStateName(s), phaserToString(phaser)); + this.newState = s; + int phase = phaser.arrive(); + System.out.format("%d: awaiting party arrive %s %s%n", + id, toStateName(s), phaserToString(phaser)); + for (;;) { + // when this thread has changed its state before it waits or parks + // on a lock, a potential race might happen if it misses the notify + // or unpark. Hence await for the phaser to advance with timeout + // to cope with this race condition. + switch (state) { + case S_WAITING: + case S_TIMED_WAITING: + synchronized (lock) { + lock.notify(); + } + break; + case S_PARKED: + case S_TIMED_PARKED: + LockSupport.unpark(this); + break; + case S_SLEEPING: + this.interrupt(); + break; + case S_BLOCKED: + default: + break; + } + try { + phaser.awaitAdvanceInterruptibly(phase, 100, TimeUnit.MILLISECONDS); + System.out.format("%d: arrived at %s %s%n", + id, toStateName(s), phaserToString(phaser)); + return; + } catch (TimeoutException ex) { + // this thread hasn't arrived at this phase + System.out.format("%d: Timeout: %s%n", id, phaser); + } + } + } + private String phaserToString(Phaser p) { + return "[phase = " + p.getPhase() + + " parties = " + p.getRegisteredParties() + + " arrived = " + p.getArrivedParties() + "]"; + } + private String toStateName(int state) { + switch (state) { + case S_RUNNABLE: + return "runnable"; + case S_WAITING: + return "waiting"; + case S_TIMED_WAITING: + return "timed waiting"; + case S_PARKED: + return "parked"; + case S_TIMED_PARKED: + return "timed parked"; + case S_SLEEPING: + return "sleeping"; + case S_BLOCKED: + return "blocked"; + case S_TERMINATE: + return "terminated"; + default: + return "unknown " + state; + } + } +} diff --git a/jdk/test/java/lang/Thread/ThreadStateTest.java b/jdk/test/java/lang/Thread/ThreadStateTest.java index c4fa18850b2..b73421eb4c0 100644 --- a/jdk/test/java/lang/Thread/ThreadStateTest.java +++ b/jdk/test/java/lang/Thread/ThreadStateTest.java @@ -21,77 +21,64 @@ * questions. */ +import static java.lang.Thread.State.*; + /* * @test - * @bug 5014783 + * @bug 5014783 8022208 * @summary Basic unit test of thread states returned by * Thread.getState(). * * @author Mandy Chung - * - * @build ThreadStateTest + * @build ThreadStateTest ThreadStateController * @run main ThreadStateTest */ -import java.util.concurrent.locks.LockSupport; -import java.util.concurrent.Phaser; - public class ThreadStateTest { - // maximum number of retries when checking for thread state. - static final int MAX_RETRY = 500; - private static boolean testFailed = false; // used to achieve waiting states - static final Object globalLock = new Object(); + private static final Object globalLock = new Object(); - public static void main(String[] argv) { + public static void main(String[] argv) throws Exception { // Call Thread.getState to force all initialization done // before test verification begins. Thread.currentThread().getState(); - MyThread myThread = new MyThread("MyThread"); + ThreadStateController thread = new ThreadStateController("StateChanger", globalLock); + thread.setDaemon(true); // before myThread starts - checkThreadState(myThread, Thread.State.NEW); + thread.checkThreadState(NEW); - myThread.start(); - myThread.waitUntilStarted(); - checkThreadState(myThread, Thread.State.RUNNABLE); + thread.start(); + thread.transitionTo(RUNNABLE); + thread.checkThreadState(RUNNABLE); synchronized (globalLock) { - myThread.goBlocked(); - checkThreadState(myThread, Thread.State.BLOCKED); + thread.transitionTo(BLOCKED); + thread.checkThreadState(BLOCKED); } - myThread.goWaiting(); - checkThreadState(myThread, Thread.State.WAITING); + thread.transitionTo(WAITING); + thread.checkThreadState(WAITING); - myThread.goTimedWaiting(); - checkThreadState(myThread, Thread.State.TIMED_WAITING); + thread.transitionTo(TIMED_WAITING); + thread.checkThreadState(TIMED_WAITING); + thread.transitionToPark(true /* timed park*/); + thread.checkThreadState(TIMED_WAITING); - /* - *********** park and parkUntil seems not working - * ignore this case for now. - * Bug ID 5062095 - *********************************************** + thread.transitionToPark(false /* indefinite park */); + thread.checkThreadState(WAITING); - myThread.goParked(); - checkThreadState(myThread, Thread.State.WAITING); + thread.transitionToSleep(); + thread.checkThreadState(TIMED_WAITING); - myThread.goTimedParked(); - checkThreadState(myThread, Thread.State.TIMED_WAITING); - */ - - - myThread.goSleeping(); - checkThreadState(myThread, Thread.State.TIMED_WAITING); - - myThread.terminate(); - checkThreadState(myThread, Thread.State.TERMINATED); + thread.transitionTo(TERMINATED); + thread.checkThreadState(TERMINATED); try { - myThread.join(); + thread.join(); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("Unexpected exception."); @@ -102,241 +89,4 @@ public class ThreadStateTest { throw new RuntimeException("TEST FAILED."); System.out.println("Test passed."); } - - private static void checkThreadState(Thread t, Thread.State expected) { - // wait for the thread to transition to the expected state. - // There is a small window between the thread checking the state - // and the thread actual entering that state. - Thread.State state; - int retryCount=0; - while ((state = t.getState()) != expected && retryCount < MAX_RETRY) { - if (state != Thread.State.RUNNABLE) { - throw new RuntimeException("Thread not in expected state yet," + - " but it should at least be RUNNABLE"); - } - goSleep(10); - retryCount++; - } - - System.out.println("Checking thread state " + state); - if (state == null) { - throw new RuntimeException(t.getName() + " expected to have " + - expected + " but got null."); - } - - if (state != expected) { - throw new RuntimeException(t.getName() + " expected to have " + - expected + " but got " + state); - } - } - - private static void goSleep(long ms) { - try { - Thread.sleep(ms); - } catch (InterruptedException e) { - e.printStackTrace(); - System.out.println("Unexpected exception."); - testFailed = true; - } - } - - static class MyThread extends Thread { - // Phaser to sync between the main thread putting - // this thread into various states - private Phaser phaser = new Phaser(2); - - MyThread(String name) { - super(name); - } - - private final int RUNNABLE = 0; - private final int BLOCKED = 1; - private final int WAITING = 2; - private final int TIMED_WAITING = 3; - private final int PARKED = 4; - private final int TIMED_PARKED = 5; - private final int SLEEPING = 6; - private final int TERMINATE = 7; - - private volatile int state = RUNNABLE; - - private boolean done = false; - public void run() { - // Signal main thread to continue. - phaser.arriveAndAwaitAdvance(); - - while (!done) { - switch (state) { - case RUNNABLE: { - double sum = 0; - for (int i = 0; i < 1000; i++) { - double r = Math.random(); - double x = Math.pow(3, r); - sum += x - r; - } - break; - } - case BLOCKED: { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to block."); - synchronized (globalLock) { - // finish blocking - state = RUNNABLE; - } - break; - } - case WAITING: { - synchronized (globalLock) { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to wait."); - try { - globalLock.wait(); - } catch (InterruptedException e) { - // ignore - } - } - break; - } - case TIMED_WAITING: { - synchronized (globalLock) { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to timed wait."); - try { - globalLock.wait(10000); - } catch (InterruptedException e) { - // ignore - } - } - break; - } - case PARKED: { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to park."); - LockSupport.park(); - // give a chance for the main thread to block - goSleep(10); - break; - } - case TIMED_PARKED: { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to timed park."); - long deadline = System.currentTimeMillis() + 10000*1000; - LockSupport.parkUntil(deadline); - - // give a chance for the main thread to block - goSleep(10); - break; - } - case SLEEPING: { - // signal main thread. - phaser.arrive(); - System.out.println(" myThread is going to sleep."); - try { - Thread.sleep(1000000); - } catch (InterruptedException e) { - // finish sleeping - } - break; - } - case TERMINATE: { - done = true; - // signal main thread. - phaser.arrive(); - break; - } - default: - break; - } - } - } - - public void waitUntilStarted() { - // wait for MyThread. - phaser.arriveAndAwaitAdvance(); - } - - public void goBlocked() { - System.out.println("Waiting myThread to go blocked."); - setState(BLOCKED); - // wait for MyThread to get to a point just before being blocked - phaser.arriveAndAwaitAdvance(); - } - - public void goWaiting() { - System.out.println("Waiting myThread to go waiting."); - setState(WAITING); - // wait for MyThread to get to just before wait on object. - phaser.arriveAndAwaitAdvance(); - } - - public void goTimedWaiting() { - System.out.println("Waiting myThread to go timed waiting."); - setState(TIMED_WAITING); - // wait for MyThread to get to just before timed wait call. - phaser.arriveAndAwaitAdvance(); - } - - public void goParked() { - System.out.println("Waiting myThread to go parked."); - setState(PARKED); - // wait for MyThread to get to just before parked. - phaser.arriveAndAwaitAdvance(); - } - - public void goTimedParked() { - System.out.println("Waiting myThread to go timed parked."); - setState(TIMED_PARKED); - // wait for MyThread to get to just before timed park. - phaser.arriveAndAwaitAdvance(); - } - - public void goSleeping() { - System.out.println("Waiting myThread to go sleeping."); - setState(SLEEPING); - // wait for MyThread to get to just before sleeping - phaser.arriveAndAwaitAdvance(); - } - - public void terminate() { - System.out.println("Waiting myThread to terminate."); - setState(TERMINATE); - // wait for MyThread to get to just before terminate - phaser.arriveAndAwaitAdvance(); - } - - private void setState(int newState) { - switch (state) { - case BLOCKED: - while (state == BLOCKED) { - goSleep(10); - } - state = newState; - break; - case WAITING: - case TIMED_WAITING: - state = newState; - synchronized (globalLock) { - globalLock.notify(); - } - break; - case PARKED: - case TIMED_PARKED: - state = newState; - LockSupport.unpark(this); - break; - case SLEEPING: - state = newState; - this.interrupt(); - break; - default: - state = newState; - break; - } - } - } } diff --git a/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java b/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java new file mode 100644 index 00000000000..dc4fe3d1016 --- /dev/null +++ b/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2003, 2006, 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 4967283 5080203 8022208 + * @summary Basic unit test of thread states returned by + * ThreadMXBean.getThreadInfo.getThreadState(). + * It also tests lock information returned by ThreadInfo. + * + * @author Mandy Chung + * + * @library ../../Thread + * @build ThreadMXBeanStateTest ThreadStateController + * @run main ThreadMXBeanStateTest + */ + +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadMXBean; +import java.lang.management.ThreadInfo; +import static java.lang.Thread.State.*; + +public class ThreadMXBeanStateTest { + private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean(); + + static class Lock { + private String name; + Lock(String name) { + this.name = name; + } + public String toString() { + return name; + } + } + private static Lock globalLock = new Lock("my lock"); + + public static void main(String[] argv) throws Exception { + // Force thread state initialization now before the test + // verification begins. + Thread.currentThread().getState(); + ThreadStateController thread = new ThreadStateController("StateChanger", globalLock); + thread.setDaemon(true); + + // before myThread starts + thread.checkThreadState(NEW); + + thread.start(); + thread.transitionTo(RUNNABLE); + thread.checkThreadState(RUNNABLE); + checkLockInfo(thread, RUNNABLE, null, null); + + thread.suspend(); + ThreadStateController.pause(10); + thread.checkThreadState(RUNNABLE); + checkSuspendedThreadState(thread, RUNNABLE); + thread.resume(); + + synchronized (globalLock) { + thread.transitionTo(BLOCKED); + thread.checkThreadState(BLOCKED); + checkLockInfo(thread, BLOCKED, + globalLock, Thread.currentThread()); + } + + thread.transitionTo(WAITING); + thread.checkThreadState(WAITING); + checkLockInfo(thread, Thread.State.WAITING, + globalLock, null); + + thread.transitionTo(TIMED_WAITING); + thread.checkThreadState(TIMED_WAITING); + checkLockInfo(thread, TIMED_WAITING, + globalLock, null); + + + thread.transitionToPark(true /* timed park */); + thread.checkThreadState(TIMED_WAITING); + checkLockInfo(thread, TIMED_WAITING, null, null); + + thread.transitionToPark(false /* indefinite park */); + thread.checkThreadState(WAITING); + checkLockInfo(thread, WAITING, null, null); + + thread.transitionToSleep(); + thread.checkThreadState(TIMED_WAITING); + checkLockInfo(thread, TIMED_WAITING, null, null); + + thread.transitionTo(TERMINATED); + thread.checkThreadState(TERMINATED); + + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + System.out.println("TEST FAILED: Unexpected exception."); + throw new RuntimeException(e); + } + System.out.println("Test passed."); + } + + private static void checkSuspendedThreadState(ThreadStateController t, Thread.State state) { + ThreadInfo info = getThreadInfo(t, state); + if (info == null) { + throw new RuntimeException(t.getName() + + " expected to have ThreadInfo " + + " but got null."); + } + + if (info.getThreadState() != state) { + throw new RuntimeException(t.getName() + " expected to be in " + + state + " state but got " + info.getThreadState()); + } + + if (!info.isSuspended()) { + throw new RuntimeException(t.getName() + " expected to be suspended " + + " but isSuspended() returns " + info.isSuspended()); + } + } + + private static String getLockName(Object lock) { + if (lock == null) return null; + + return lock.getClass().getName() + '@' + + Integer.toHexString(System.identityHashCode(lock)); + } + + // maximum number of retries when checking for thread state. + private static final int MAX_RETRY = 500; + private static ThreadInfo getThreadInfo(ThreadStateController t, Thread.State expected) { + // wait for the thread to transition to the expected state. + // There is a small window between the thread checking the state + // and the thread actual entering that state. + int retryCount=0; + ThreadInfo info = tm.getThreadInfo(t.getId()); + while (info.getThreadState() != expected && retryCount < MAX_RETRY) { + ThreadStateController.pause(10); + retryCount++; + info = tm.getThreadInfo(t.getId()); + } + return info; + } + + private static void checkLockInfo(ThreadStateController t, Thread.State state, + Object lock, Thread owner) { + ThreadInfo info = getThreadInfo(t, state); + if (info == null) { + throw new RuntimeException(t.getName() + + " expected to have ThreadInfo " + + " but got null."); + } + + if (info.getThreadState() != state) { + throw new RuntimeException(t.getName() + " expected to be in " + + state + " state but got " + info.getThreadState()); + } + + if (lock == null && info.getLockName() != null) { + throw new RuntimeException(t.getName() + + " expected not to be blocked on any lock" + + " but got " + info.getLockName()); + } + String expectedLockName = getLockName(lock); + if (lock != null && info.getLockName() == null) { + throw new RuntimeException(t.getName() + + " expected to be blocked on lock [" + expectedLockName + + "] but got null."); + } + + if (lock != null && !expectedLockName.equals(info.getLockName())) { + throw new RuntimeException(t.getName() + + " expected to be blocked on lock [" + expectedLockName + + "] but got [" + info.getLockName() + "]."); + } + + if (owner == null && info.getLockOwnerName() != null) { + throw new RuntimeException("Lock owner is expected " + + " to be null but got " + info.getLockOwnerName()); + } + + if (owner != null && info.getLockOwnerName() == null) { + throw new RuntimeException("Lock owner is expected to be " + + owner.getName() + + " but got null."); + } + if (owner != null && !info.getLockOwnerName().equals(owner.getName())) { + throw new RuntimeException("Lock owner is expected to be " + + owner.getName() + + " but got " + owner.getName()); + } + if (owner == null && info.getLockOwnerId() != -1) { + throw new RuntimeException("Lock owner is expected " + + " to be -1 but got " + info.getLockOwnerId()); + } + + if (owner != null && info.getLockOwnerId() <= 0) { + throw new RuntimeException("Lock owner is expected to be " + + owner.getName() + "(id = " + owner.getId() + + ") but got " + info.getLockOwnerId()); + } + if (owner != null && info.getLockOwnerId() != owner.getId()) { + throw new RuntimeException("Lock owner is expected to be " + + owner.getName() + "(id = " + owner.getId() + + ") but got " + info.getLockOwnerId()); + } + if (info.isSuspended()) { + throw new RuntimeException(t.getName() + + " isSuspended() returns " + info.isSuspended()); + } + } +} diff --git a/jdk/test/java/lang/management/ThreadMXBean/ThreadStateTest.java b/jdk/test/java/lang/management/ThreadMXBean/ThreadStateTest.java deleted file mode 100644 index 1b767e46225..00000000000 --- a/jdk/test/java/lang/management/ThreadMXBean/ThreadStateTest.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (c) 2003, 2006, 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 4967283 5080203 - * @summary Basic unit test of thread states returned by - * ThreadMXBean.getThreadInfo.getThreadState(). - * It also tests lock information returned by ThreadInfo. - * - * @author Mandy Chung - * - * @build ThreadExecutionSynchronizer Utils - * @run main ThreadStateTest - */ - -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadMXBean; -import java.lang.management.ThreadInfo; - -import java.util.concurrent.locks.LockSupport; - -public class ThreadStateTest { - private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean(); - - static class Lock { - private String name; - Lock(String name) { - this.name = name; - } - public String toString() { - return name; - } - } - private static Lock globalLock = new Lock("my lock"); - - public static void main(String[] argv) { - // Force thread state initialization now before the test - // verification begins. - Thread.currentThread().getState(); - - MyThread myThread = new MyThread("MyThread"); - - // before myThread starts - // Utils.checkThreadState(myThread, Thread.State.NEW); - - myThread.start(); - myThread.waitUntilStarted(); - Utils.checkThreadState(myThread, Thread.State.RUNNABLE); - checkLockInfo(myThread, Thread.State.RUNNABLE, null, null); - - myThread.suspend(); - Utils.goSleep(10); - checkSuspendedThreadState(myThread, Thread.State.RUNNABLE); - myThread.resume(); - - synchronized (globalLock) { - myThread.goBlocked(); - Utils.checkThreadState(myThread, Thread.State.BLOCKED); - checkLockInfo(myThread, Thread.State.BLOCKED, - globalLock, Thread.currentThread()); - } - - myThread.goWaiting(); - Utils.checkThreadState(myThread, Thread.State.WAITING); - checkLockInfo(myThread, Thread.State.WAITING, - globalLock, null); - - myThread.goTimedWaiting(); - Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING); - checkLockInfo(myThread, Thread.State.TIMED_WAITING, - globalLock, null); - - - - /* - *********** parkUntil seems not working - * ignore this park case for now. - - Bug ID : 5062095 - *********************************************** - myThread.goParked(); - Utils.checkThreadState(myThread, Thread.State.WAITING); - checkLockInfo(myThread, Thread.State.WAITING, null, null); - - myThread.goTimedParked(); - Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING); - checkLockInfo(myThread, Thread.State.TIMED_WAITING, null, null); - - */ - - myThread.goSleeping(); - Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING); - checkLockInfo(myThread, Thread.State.TIMED_WAITING, null, null); - - - myThread.terminate(); - // Utils.checkThreadState(myThread, ThreadState.TERMINATED); - - try { - myThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - System.out.println("TEST FAILED: Unexpected exception."); - throw new RuntimeException(e); - } - System.out.println("Test passed."); - } - - private static void checkSuspendedThreadState(Thread t, Thread.State state) { - ThreadInfo info = tm.getThreadInfo(t.getId()); - if (info == null) { - throw new RuntimeException(t.getName() + - " expected to have ThreadInfo " + - " but got null."); - } - - if (info.getThreadState() != state) { - throw new RuntimeException(t.getName() + " expected to be in " + - state + " state but got " + info.getThreadState()); - } - - if (!info.isSuspended()) { - throw new RuntimeException(t.getName() + " expected to be suspended " + - " but isSuspended() returns " + info.isSuspended()); - } - Utils.checkThreadState(t, state); - } - - private static String getLockName(Object lock) { - if (lock == null) return null; - - return lock.getClass().getName() + '@' + - Integer.toHexString(System.identityHashCode(lock)); - } - - private static void checkLockInfo(Thread t, Thread.State state, Object lock, Thread owner) { - ThreadInfo info = tm.getThreadInfo(t.getId()); - if (info == null) { - throw new RuntimeException(t.getName() + - " expected to have ThreadInfo " + - " but got null."); - } - - if (info.getThreadState() != state) { - throw new RuntimeException(t.getName() + " expected to be in " + - state + " state but got " + info.getThreadState()); - } - - if (lock == null && info.getLockName() != null) { - throw new RuntimeException(t.getName() + - " expected not to be blocked on any lock" + - " but got " + info.getLockName()); - } - String expectedLockName = getLockName(lock); - if (lock != null && info.getLockName() == null) { - throw new RuntimeException(t.getName() + - " expected to be blocked on lock [" + expectedLockName + - "] but got null."); - } - - if (lock != null && !expectedLockName.equals(info.getLockName())) { - throw new RuntimeException(t.getName() + - " expected to be blocked on lock [" + expectedLockName + - "] but got [" + info.getLockName() + "]."); - } - - if (owner == null && info.getLockOwnerName() != null) { - throw new RuntimeException("Lock owner is expected " + - " to be null but got " + info.getLockOwnerName()); - } - - if (owner != null && info.getLockOwnerName() == null) { - throw new RuntimeException("Lock owner is expected to be " + - owner.getName() + - " but got null."); - } - if (owner != null && !info.getLockOwnerName().equals(owner.getName())) { - throw new RuntimeException("Lock owner is expected to be " + - owner.getName() + - " but got " + owner.getName()); - } - if (owner == null && info.getLockOwnerId() != -1) { - throw new RuntimeException("Lock owner is expected " + - " to be -1 but got " + info.getLockOwnerId()); - } - - if (owner != null && info.getLockOwnerId() <= 0) { - throw new RuntimeException("Lock owner is expected to be " + - owner.getName() + "(id = " + owner.getId() + - ") but got " + info.getLockOwnerId()); - } - if (owner != null && info.getLockOwnerId() != owner.getId()) { - throw new RuntimeException("Lock owner is expected to be " + - owner.getName() + "(id = " + owner.getId() + - ") but got " + info.getLockOwnerId()); - } - if (info.isSuspended()) { - throw new RuntimeException(t.getName() + - " isSuspended() returns " + info.isSuspended()); - } - } - - static class MyThread extends Thread { - private ThreadExecutionSynchronizer thrsync = new ThreadExecutionSynchronizer(); - - MyThread(String name) { - super(name); - } - - private final int RUNNABLE = 0; - private final int BLOCKED = 1; - private final int WAITING = 2; - private final int TIMED_WAITING = 3; - private final int PARKED = 4; - private final int TIMED_PARKED = 5; - private final int SLEEPING = 6; - private final int TERMINATE = 7; - private int state = RUNNABLE; - - private boolean done = false; - public void run() { - // Signal main thread to continue. - thrsync.signal(); - while (!done) { - switch (state) { - case RUNNABLE: { - double sum = 0; - for (int i = 0; i < 1000; i++) { - double r = Math.random(); - double x = Math.pow(3, r); - sum += x - r; - } - break; - } - case BLOCKED: { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to block."); - synchronized (globalLock) { - // finish blocking - state = RUNNABLE; - } - break; - } - case WAITING: { - synchronized (globalLock) { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to wait."); - try { - globalLock.wait(); - } catch (InterruptedException e) { - // ignore - } - } - break; - } - case TIMED_WAITING: { - synchronized (globalLock) { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to timed wait."); - try { - globalLock.wait(10000); - } catch (InterruptedException e) { - // ignore - } - } - break; - } - case PARKED: { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to park."); - LockSupport.park(); - // give a chance for the main thread to block - System.out.println(" myThread is going to park."); - Utils.goSleep(10); - break; - } - case TIMED_PARKED: { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to timed park."); - long deadline = System.currentTimeMillis() + 10000*1000; - LockSupport.parkUntil(deadline); - - // give a chance for the main thread to block - Utils.goSleep(10); - break; - } - case SLEEPING: { - // signal main thread. - thrsync.signal(); - System.out.println(" myThread is going to sleep."); - try { - Thread.sleep(1000000); - } catch (InterruptedException e) { - // finish sleeping - interrupted(); - } - break; - } - case TERMINATE: { - done = true; - // signal main thread. - thrsync.signal(); - break; - } - default: - break; - } - } - } - public void waitUntilStarted() { - // wait for MyThread. - thrsync.waitForSignal(); - Utils.goSleep(10); - } - - public void goBlocked() { - System.out.println("Waiting myThread to go blocked."); - setState(BLOCKED); - // wait for MyThread to get blocked - thrsync.waitForSignal(); - Utils.goSleep(20); - } - - public void goWaiting() { - System.out.println("Waiting myThread to go waiting."); - setState(WAITING); - // wait for MyThread to wait on object. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - public void goTimedWaiting() { - System.out.println("Waiting myThread to go timed waiting."); - setState(TIMED_WAITING); - // wait for MyThread timed wait call. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - public void goParked() { - System.out.println("Waiting myThread to go parked."); - setState(PARKED); - // wait for MyThread state change to PARKED. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - public void goTimedParked() { - System.out.println("Waiting myThread to go timed parked."); - setState(TIMED_PARKED); - // wait for MyThread. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - - public void goSleeping() { - System.out.println("Waiting myThread to go sleeping."); - setState(SLEEPING); - // wait for MyThread. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - public void terminate() { - System.out.println("Waiting myThread to terminate."); - setState(TERMINATE); - // wait for MyThread. - thrsync.waitForSignal(); - Utils.goSleep(20); - } - - private void setState(int newState) { - switch (state) { - case BLOCKED: - while (state == BLOCKED) { - Utils.goSleep(20); - } - state = newState; - break; - case WAITING: - case TIMED_WAITING: - state = newState; - synchronized (globalLock) { - globalLock.notify(); - } - break; - case PARKED: - case TIMED_PARKED: - state = newState; - LockSupport.unpark(this); - break; - case SLEEPING: - state = newState; - this.interrupt(); - break; - default: - state = newState; - break; - } - } - } -} From 4f0480aaeb20f7a776917008275972f03014d5eb Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Tue, 5 Nov 2013 19:44:41 -0800 Subject: [PATCH 15/74] 8021309: replace test/Makefile jdk_* targets with jtreg groups 8015068: Use jtreg -exclude for handling problemList.txt exclusions Reviewed-by: jjg, smarks, chegar, alanb, dholmes --- jdk/.hgignore | 1 + jdk/test/Makefile | 471 ++++++---------------------------------------- 2 files changed, 63 insertions(+), 409 deletions(-) diff --git a/jdk/.hgignore b/jdk/.hgignore index e849b9e6d1f..d8754b13e1f 100644 --- a/jdk/.hgignore +++ b/jdk/.hgignore @@ -1,5 +1,6 @@ ^build/ ^dist/ +^testoutput/ /nbproject/private/ ^make/netbeans/.*/build/ ^make/netbeans/.*/dist/ diff --git a/jdk/test/Makefile b/jdk/test/Makefile index c4a9b93bec6..9a9092df16b 100644 --- a/jdk/test/Makefile +++ b/jdk/test/Makefile @@ -27,6 +27,8 @@ # Makefile to run various jdk tests # +.DEFAULT : all + # Empty these to get rid of some default rules .SUFFIXES: .SUFFIXES: .java @@ -55,150 +57,19 @@ UNIQ = uniq WC = wc ZIP = zip -# Get OS name from uname -UNAME_S := $(shell $(UNAME) -s) +# Get OS name from uname (Cygwin inexplicably adds _NT-5.1) +UNAME_S := $(shell $(UNAME) -s | $(CUT) -f1 -d_) # Commands to run on paths to make mixed paths for java on windows -GETMIXEDPATH=$(ECHO) - -# Location of developer shared files -SLASH_JAVA = /java - -# Platform specific settings -ifeq ($(UNAME_S), SunOS) - OS_NAME = solaris - OS_ARCH := $(shell $(UNAME) -p) - OS_VERSION := $(shell $(UNAME) -r) -endif -ifeq ($(UNAME_S), Linux) - OS_NAME = linux - OS_ARCH := $(shell $(UNAME) -m) - # Check for unknown arch, try uname -p if uname -m says unknown - ifeq ($(OS_ARCH),unknown) - OS_ARCH := $(shell $(UNAME) -p) - endif - OS_VERSION := $(shell $(UNAME) -r) -endif -ifeq ($(UNAME_S), Darwin) - OS_NAME = macosx - OS_ARCH := $(shell $(UNAME) -m) - # Check for unknown arch, try uname -p if uname -m says unknown - ifeq ($(OS_ARCH),unknown) - OS_ARCH := $(shell $(UNAME) -p) - endif - OS_VERSION := $(shell $(UNAME) -r) -endif -ifeq ($(OS_NAME),) - OS_NAME = windows - # GNU Make or MKS overrides $(PROCESSOR_ARCHITECTURE) to always - # return "x86". Use the first word of $(PROCESSOR_IDENTIFIER) instead. - ifeq ($(PROCESSOR_IDENTIFIER),) - PROC_ARCH:=$(shell $(UNAME) -m) - else - PROC_ARCH:=$(word 1, $(PROCESSOR_IDENTIFIER)) - endif - OS_ARCH:=$(PROC_ARCH) +ifeq ($(UNAME_S), CYGWIN) + # Location of developer shared files SLASH_JAVA = J: - EXESUFFIX = .exe - # These need to be different depending on MKS or CYGWIN - ifeq ($(findstring cygdrive,$(shell ($(CD) C:/ && $(PWD)))), ) - GETMIXEDPATH = dosname -s - OS_VERSION := $(shell $(UNAME) -r) - else - GETMIXEDPATH = cygpath -m -s - OS_VERSION := $(shell $(UNAME) -s | $(CUT) -d'-' -f2) - endif -endif - -# Only want major and minor numbers from os version -OS_VERSION := $(shell $(ECHO) "$(OS_VERSION)" | $(CUT) -d'.' -f1,2) - -# Name to use for x86_64 arch (historically amd64, but should change someday) -OS_ARCH_X64_NAME:=amd64 -#OS_ARCH_X64_NAME:=x64 - -# Alternate arch names (in case this arch is known by a second name) -# PROBLEM_LISTS may use either name. -OS_ARCH2-amd64:=x64 -#OS_ARCH2-x64:=amd64 - -# Try and use the arch names consistently -OS_ARCH:=$(patsubst x64,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst X64,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst AMD64,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst amd64,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst x86_64,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst 8664,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst EM64T,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst em64t,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst intel64,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst Intel64,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst INTEL64,$(OS_ARCH_X64_NAME),$(OS_ARCH)) -OS_ARCH:=$(patsubst IA64,ia64,$(OS_ARCH)) -OS_ARCH:=$(patsubst X86,i586,$(OS_ARCH)) -OS_ARCH:=$(patsubst x86,i586,$(OS_ARCH)) -OS_ARCH:=$(patsubst i386,i586,$(OS_ARCH)) -OS_ARCH:=$(patsubst i486,i586,$(OS_ARCH)) -OS_ARCH:=$(patsubst i686,i586,$(OS_ARCH)) -OS_ARCH:=$(patsubst 386,i586,$(OS_ARCH)) -OS_ARCH:=$(patsubst 486,i586,$(OS_ARCH)) -OS_ARCH:=$(patsubst 586,i586,$(OS_ARCH)) -OS_ARCH:=$(patsubst 686,i586,$(OS_ARCH)) - -# Default ARCH_DATA_MODEL settings -ARCH_DATA_MODEL-i586 = 32 -ARCH_DATA_MODEL-$(OS_ARCH_X64_NAME) = 64 -ARCH_DATA_MODEL-ia64 = 64 -ARCH_DATA_MODEL-sparc = 32 -ARCH_DATA_MODEL-sparcv9 = 64 - -# If ARCH_DATA_MODEL is not defined, try and pick a reasonable default -ifndef ARCH_DATA_MODEL - ARCH_DATA_MODEL:=$(ARCH_DATA_MODEL-$(OS_ARCH)) -endif -ifndef ARCH_DATA_MODEL - ARCH_DATA_MODEL=32 -endif - -# Platform directory name -PLATFORM_OS = $(OS_NAME)-$(OS_ARCH) - -# Check ARCH_DATA_MODEL, adjust OS_ARCH accordingly on solaris -ARCH_DATA_MODEL_ERROR= \ - ARCH_DATA_MODEL=$(ARCH_DATA_MODEL) cannot be used with $(PLATFORM_OS) -ifeq ($(ARCH_DATA_MODEL),64) - ifeq ($(PLATFORM_OS),solaris-i586) - OS_ARCH=$(OS_ARCH_X64_NAME) - endif - ifeq ($(PLATFORM_OS),solaris-sparc) - OS_ARCH=sparcv9 - endif - ifeq ($(OS_ARCH),i586) - x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)") - endif - ifeq ($(OS_ARCH),sparc) - x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)") - endif + GETMIXEDPATH = cygpath -m -s else - ifeq ($(ARCH_DATA_MODEL),32) - ifeq ($(OS_ARCH),$(OS_ARCH_X64_NAME)) - x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)") - endif - ifeq ($(OS_ARCH),ia64) - x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)") - endif - ifeq ($(OS_ARCH),sparcv9) - x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)") - endif - else - x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)") - endif -endif + # Location of developer shared files + SLASH_JAVA = /java -# Alternate OS_ARCH name (defaults to OS_ARCH) -OS_ARCH2:=$(OS_ARCH2-$(OS_ARCH)) -ifeq ($(OS_ARCH2),) - OS_ARCH2:=$(OS_ARCH) + GETMIXEDPATH=$(ECHO) endif # Root of this test area (important to use full paths in some places) @@ -206,17 +77,18 @@ TEST_ROOT := $(shell $(PWD)) # Root of all test results ifdef ALT_OUTPUTDIR - ABS_OUTPUTDIR = $(ALT_OUTPUTDIR) + ABS_OUTPUTDIR = $(shell $(CD) $(ALT_OUTPUTDIR) && $(PWD)) else - ABS_OUTPUTDIR = $(TEST_ROOT)/../build/$(PLATFORM_OS) + ABS_OUTPUTDIR = $(shell $(CD) $(TEST_ROOT)/.. && $(PWD)) endif + ABS_PLATFORM_BUILD_ROOT = $(ABS_OUTPUTDIR) ABS_TEST_OUTPUT_DIR := $(ABS_PLATFORM_BUILD_ROOT)/testoutput/$(UNIQUE_DIR) # Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test) ifndef PRODUCT_HOME # Try to use j2sdk-image if it exists - ABS_JDK_IMAGE = $(ABS_PLATFORM_BUILD_ROOT)/j2sdk-image + ABS_JDK_IMAGE = $(ABS_PLATFORM_BUILD_ROOT)/images/j2sdk-image PRODUCT_HOME := \ $(shell \ if [ -d $(ABS_JDK_IMAGE) ] ; then \ @@ -240,30 +112,11 @@ ifdef JPRT_PRODUCT_VM_ARGS JAVA_VM_ARGS = $(JPRT_PRODUCT_VM_ARGS) endif -# Check JAVA_ARGS arguments based on ARCH_DATA_MODEL etc. -ifeq ($(OS_NAME),solaris) - D64_ERROR_MESSAGE=Mismatch between ARCH_DATA_MODEL=$(ARCH_DATA_MODEL) and use of -d64 in JAVA_ARGS=$(JAVA_ARGS) - ifeq ($(ARCH_DATA_MODEL),32) - ifneq ($(findstring -d64,$(JAVA_ARGS)),) - x:=$(warning "WARNING: $(D64_ERROR_MESSAGE)") - endif - endif - ifeq ($(ARCH_DATA_MODEL),64) - ifeq ($(findstring -d64,$(JAVA_ARGS)),) - x:=$(warning "WARNING: $(D64_ERROR_MESSAGE)") - endif - endif -endif - -# Macro to run make and set the shared library permissions -define SharedLibraryPermissions -$(MAKE) SHARED_LIBRARY_DIR=$1 UNIQUE_DIR=$@ shared_library_permissions -endef - # Expect JPRT to set JPRT_ARCHIVE_BUNDLE (path to zip bundle for results) -ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip ifdef JPRT_ARCHIVE_BUNDLE ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE) +else + ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip endif # How to create the test bundle (pass or fail, we want to create this) @@ -272,13 +125,15 @@ ZIP_UP_RESULTS = ( $(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)` \ && $(CD) $(ABS_TEST_OUTPUT_DIR) \ && $(CHMOD) -R a+r . \ && $(ZIP) -q -r $(ARCHIVE_BUNDLE) . ) -SUMMARY_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport/text/summary.txt + +# important results files +SUMMARY_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport/text/summary.txt") STATS_TXT_NAME = Stats.txt -STATS_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/$(STATS_TXT_NAME) -RUNLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/runlist.txt -PASSLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/passlist.txt -FAILLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/faillist.txt -EXITCODE = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/exitcode.txt +STATS_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/$(STATS_TXT_NAME)") +RUNLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/runlist.txt") +PASSLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/passlist.txt") +FAILLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/faillist.txt") +EXITCODE = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/exitcode.txt") TESTEXIT = \ if [ ! -s $(EXITCODE) ] ; then \ @@ -316,8 +171,8 @@ BUNDLE_UP_AND_EXIT = \ runc="`$(CAT) $(RUNLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \ passc="`$(CAT) $(PASSLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \ failc="`$(CAT) $(FAILLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \ - exclc="`$(CAT) $(EXCLUDELIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \ - $(ECHO) "TEST STATS: name=$(UNIQUE_DIR) run=$${runc} pass=$${passc} fail=$${failc} excluded=$${exclc}" \ + exclc="FIXME CODETOOLS-7900176"; \ + $(ECHO) "TEST STATS: name=$(UNIQUE_DIR) run=$${runc} pass=$${passc} fail=$${failc}" \ >> $(STATS_TXT); \ else \ $(ECHO) "Missing file: $${_summary}" >> $(STATS_TXT); \ @@ -336,9 +191,24 @@ all: jdk_default @$(ECHO) "Testing completed successfully" # Prep for output +# Change execute permissions on shared library files. +# Files in repositories should never have execute permissions, but +# there are some tests that have pre-built shared libraries, and these +# windows dll files must have execute permission. Adding execute +# permission may happen automatically on windows when using certain +# versions of mercurial but it cannot be guaranteed. And blindly +# adding execute permission might be seen as a mercurial 'change', so +# we avoid adding execute permission to repository files. But testing +# from a plain source tree needs the chmod a+rx. Applying the chmod to +# all shared libraries not just dll files. And with CYGWIN and sshd +# service, you may need CYGWIN=ntsec for this to work. prep: @$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR) @$(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)` + @if [ ! -d $(TEST_ROOT)/../.hg ] ; then \ + $(FIND) $(TEST_ROOT) \( -name \*.dll -o -name \*.DLL -o -name \*.so \) \ + -exec $(CHMOD) a+rx {} \; ; \ + fi # Cleanup clean: @@ -357,50 +227,21 @@ ifndef JT_HOME endif endif -# Expect JPRT to set TESTDIRS to the jtreg test dirs -ifndef TESTDIRS - TESTDIRS = demo -endif - -# Some tests annoy me and fail frequently -PROBLEM_LIST=ProblemList.txt -PROBLEM_LISTS=$(PROBLEM_LIST) $(wildcard closed/$(PROBLEM_LIST)) -EXCLUDELIST=$(ABS_TEST_OUTPUT_DIR)/excludelist.txt +# Problematic tests to be excluded +PROBLEM_LISTS=$(call MixedDirs,$(wildcard ProblemList.txt closed/ProblemList.txt)) # Create exclude list for this platform and arch ifdef NO_EXCLUDES -$(EXCLUDELIST): $(PROBLEM_LISTS) $(TEST_DEPENDENCIES) - @$(ECHO) "NOTHING_EXCLUDED" > $@ + JTREG_EXCLUSIONS = else -$(EXCLUDELIST): $(PROBLEM_LISTS) $(TEST_DEPENDENCIES) - @$(RM) $@ $@.temp1 $@.temp2 - @(($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- '$(OS_NAME)-all' ) ;\ - ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- '$(PLATFORM_OS)' ) ;\ - ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- '$(OS_NAME)-$(OS_ARCH2)' ) ;\ - ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- '$(OS_NAME)-$(OS_VERSION)') ;\ - ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- 'generic-$(OS_ARCH)' ) ;\ - ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- 'generic-$(OS_ARCH2)' ) ;\ - ($(CAT) $(PROBLEM_LISTS) | $(EGREP) -- 'generic-all' ) ;\ - ($(ECHO) "#") ;\ - ) | $(SED) -e 's@^[\ ]*@@' \ - | $(EGREP) -v '^#' > $@.temp1 - @for tdir in $(TESTDIRS) SOLARIS_10_SH_BUG_NO_EMPTY_FORS ; do \ - ( ( $(CAT) $@.temp1 | $(EGREP) "^$${tdir}" ) ; $(ECHO) "#" ) >> $@.temp2 ; \ - done - @$(ECHO) "# at least one line" >> $@.temp2 - @( $(EGREP) -v '^#' $@.temp2 ; true ) > $@ - @$(ECHO) "Excluding list contains `$(EXPAND) $@ | $(WC) -l` items" + JTREG_EXCLUSIONS = $(PROBLEM_LISTS:%=-exclude:%) endif -# Select list of directories that exist -define TestDirs -$(foreach i,$1,$(wildcard ${i})) $(foreach i,$1,$(wildcard closed/${i})) -endef -# Running batches of tests with or without agentvm -define RunBatch -$(ECHO) "Running tests: $?" -$(MAKE) TEST_DEPENDENCIES="$?" TESTDIRS="$?" UNIQUE_DIR=$@ jtreg_tests +# convert list of directories to dos paths +define MixedDirs +$(foreach i,$1,$(shell $(GETMIXEDPATH) "${i}")) endef + define SummaryInfo $(ECHO) "########################################################" $(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME)) @@ -409,178 +250,11 @@ endef # ------------------------------------------------------------------ -# Batches of tests (somewhat arbitrary assigments to jdk_* targets) -# NOTE: These *do not* run the same tests as make/jprt.properties -JDK_DEFAULT_TARGETS = -JDK_ALL_TARGETS = - -JDK_ALL_TARGETS += jdk_awt -jdk_awt: $(call TestDirs, com/sun/awt java/awt sun/awt \ - javax/imageio javax/print sun/pisces) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_beans1 -JDK_DEFAULT_TARGETS += jdk_beans1 -jdk_beans1: $(call TestDirs, \ - java/beans/beancontext java/beans/PropertyChangeSupport \ - java/beans/Introspector java/beans/Performance \ - java/beans/VetoableChangeSupport java/beans/Statement) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_beans2 -jdk_beans2: $(call TestDirs, \ - java/beans/Beans java/beans/EventHandler java/beans/XMLDecoder \ - java/beans/PropertyEditor) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_beans3 -jdk_beans3: $(call TestDirs, java/beans/XMLEncoder) - $(call RunBatch) - -# All beans tests -jdk_beans: jdk_beans1 jdk_beans2 jdk_beans3 - @$(SummaryInfo) - -JDK_ALL_TARGETS += jdk_io -JDK_DEFAULT_TARGETS += jdk_io -jdk_io: $(call TestDirs, java/io) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_lang -JDK_DEFAULT_TARGETS += jdk_lang -jdk_lang: $(call TestDirs, java/lang sun/invoke sun/misc sun/reflect vm) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_jmx -jdk_jmx: $(call TestDirs, javax/management com/sun/jmx) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_management -jdk_management: $(call TestDirs, com/sun/management sun/management) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_math -JDK_DEFAULT_TARGETS += jdk_math -jdk_math: $(call TestDirs, java/math) - $(call RunBatch) - -JDK_DEFAULT_TARGETS += jdk_time -jdk_time: $(call TestDirs, java/time) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_other -JDK_DEFAULT_TARGETS += jdk_other -jdk_other: $(call TestDirs, \ - demo/jvmti demo/zipfs sample \ - javax/naming com/sun/jndi \ - javax/script \ - java/sql javax/sql \ - javax/smartcardio \ - javax/xml/jaxp \ - javax/xml/soap \ - javax/xml/ws com/sun/internal/ws com/sun/org/glassfish \ - jdk/asm \ - jdk/lambda \ - com/sun/org/apache/xerces \ - com/sun/corba \ - com/sun/tracing \ - sun/usagetracker \ - misc) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_net -JDK_DEFAULT_TARGETS += jdk_net -jdk_net: $(call TestDirs, com/sun/net java/net sun/net com/oracle/net) - $(call RunBatch) - -jdk_nio: $(call TestDirs, java/nio sun/nio com/oracle/nio) - $(call SharedLibraryPermissions,java/nio/channels) - $(call RunBatch) - -jdk_sctp: $(call TestDirs, com/sun/nio/sctp) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_rmi -jdk_rmi: $(call TestDirs, java/rmi sun/rmi javax/rmi/ssl) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_security1 -JDK_DEFAULT_TARGETS += jdk_security1 -jdk_security1: $(call TestDirs, java/security) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_security2 -jdk_security2: $(call TestDirs, javax/crypto javax/xml/crypto com/sun/crypto) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_security3 -jdk_security3: $(call TestDirs, com/sun/security lib/security javax/security \ - sun/security com/sun/org/apache/xml/internal/security \ - com/oracle/security) - $(call SharedLibraryPermissions,sun/security) - $(call RunBatch) - -# All security tests -jdk_security: jdk_security1 jdk_security2 jdk_security3 - @$(SummaryInfo) - -JDK_ALL_TARGETS += jdk_sound -jdk_sound: $(call TestDirs, javax/sound) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_swing -jdk_swing: $(call TestDirs, javax/swing sun/java2d \ - demo/jfc com/sun/java/swing) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_text -JDK_DEFAULT_TARGETS += jdk_text -jdk_text: $(call TestDirs, java/text sun/text) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_jdi -jdk_jdi: $(call TestDirs, com/sun/jdi) - $(call RunBatch) - -JDK_ALL_TARGETS += jdk_tools -jdk_tools: $(call TestDirs, com/sun/tools sun/jvmstat sun/tools tools) - $(call SharedLibraryPermissions,tools/launcher) - $(call RunBatch) - -ifdef OPENJDK -jdk_jfr: -else -JDK_ALL_TARGETS += jdk_jfr -jdk_jfr: $(call TestDirs, com/oracle/jfr) - $(call RunBatch) -endif - -JDK_ALL_TARGETS += jdk_util -JDK_DEFAULT_TARGETS += jdk_util -jdk_util: $(call TestDirs, java/util sun/util) - $(call RunBatch) - -# ------------------------------------------------------------------ - -# Run default tests -# note that this *does not* have the same meaning as jprt.properties :: jprt.make.rule.default.test.targets -jdk_default: $(JDK_DEFAULT_TARGETS) - @$(SummaryInfo) - -# Run core tests -# please keep this in sync with jdk/make/jprt.properties :: jprt.make.rule.core.test.targets -jdk_core: jdk_lang jdk_math jdk_util jdk_io jdk_net jdk_nio \ - jdk_security1 jdk_security2 jdk_security3 jdk_rmi \ - jdk_management jdk_jmx jdk_text jdk_tools jdk_jfr jdk_other - @$(SummaryInfo) - -# Run all tests -# note that this *does not* have the same meaning as jprt.properties :: jprt.make.rule.all.test.targets -jdk_all: $(JDK_ALL_TARGETS) - @$(SummaryInfo) - -# These are all phony targets -PHONY_LIST += $(JDK_ALL_TARGETS) jdk_default jdk_core jdk_all +jdk_%: + $(ECHO) "Running tests: $@" + for each in $@; do \ + $(MAKE) -j 1 TEST_SELECTION=":$$each" UNIQUE_DIR=$$each jtreg_tests; \ + done # ------------------------------------------------------------------ @@ -625,44 +299,23 @@ JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION) $(JTREG): $(JT_HOME) # Run jtreg -jtreg_tests: prep $(PRODUCT_HOME) $(JTREG) $(EXCLUDELIST) - @$(EXPAND) $(EXCLUDELIST) \ - | $(CUT) -d' ' -f1 \ - | $(SED) -e 's@^@Excluding: @' +jtreg_tests: prep $(PRODUCT_HOME) $(JTREG) ( \ ( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)"); \ export JT_HOME; \ $(shell $(GETMIXEDPATH) "$(JTREG)") \ $(JTREG_BASIC_OPTIONS) \ - -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport \ - -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork \ + -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport") \ + -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTwork") \ -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)") \ - -exclude:$(shell $(GETMIXEDPATH) "$(EXCLUDELIST)") \ + $(JTREG_EXCLUSIONS) \ $(JTREG_TEST_OPTIONS) \ - $(TESTDIRS) \ - ) ; $(BUNDLE_UP_AND_EXIT) \ + $(TEST_SELECTION) \ + ) ; \ + $(BUNDLE_UP_AND_EXIT) \ ) 2>&1 | $(TEE) $(ABS_TEST_OUTPUT_DIR)/output.txt ; $(TESTEXIT) -# Rule that may change execute permissions on shared library files. -# Files in repositories should never have execute permissions, but there -# are some tests that have pre-built shared libraries, and these windows -# dll files must have execute permission. Adding execute permission -# may happen automatically on windows when using certain versions of mercurial -# but it cannot be guaranteed. And blindly adding execute permission might -# be seen as a mercurial 'change', so we avoid adding execute permission to -# repository files. But testing from a plain source tree needs the chmod a+rx. -# Used on select directories and applying the chmod to all shared libraries -# not just dll files. On windows, this may not work with MKS if the files -# were installed with CYGWIN unzip or untar (MKS chmod may not do anything). -# And with CYGWIN and sshd service, you may need CYGWIN=ntsec for this to work. -# -shared_library_permissions: $(SHARED_LIBRARY_DIR) - if [ ! -d $(TEST_ROOT)/../.hg ] ; then \ - $(FIND) $< \( -name \*.dll -o -name \*.DLL -o -name \*.so \) \ - -exec $(CHMOD) a+rx {} \; ; \ - fi - -PHONY_LIST += jtreg_tests shared_library_permissions +PHONY_LIST += jtreg_tests ################################################################ From 5eb7e21cc91150c46e0c890d2422c0951166f41f Mon Sep 17 00:00:00 2001 From: Anthony Juckel Date: Wed, 6 Nov 2013 13:25:24 -0800 Subject: [PATCH 16/74] 8025698: (fs) Typo in exception thrown by encode() in UnixPath.java Reviewed-by: dxu, mduigou, henryjen, weijun --- jdk/src/solaris/classes/sun/nio/fs/UnixPath.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java index aa04538cb20..1142b4c775b 100644 --- a/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java +++ b/jdk/src/solaris/classes/sun/nio/fs/UnixPath.java @@ -145,7 +145,7 @@ class UnixPath } if (error) { throw new InvalidPathException(input, - "Malformed input or input contains unmappable chacraters"); + "Malformed input or input contains unmappable characters"); } // trim result to actual length if required From 23d71ee6eed0f727935ad51f8b150e185c293cb7 Mon Sep 17 00:00:00 2001 From: Eric Bruneton Date: Wed, 6 Nov 2013 11:22:15 -0800 Subject: [PATCH 17/74] 8027227: [asm] generate CONSTANT_InterfaceMethodref for invoke{special/static) of non-abstract methods on ifaces Co-authored-by: Remi Forax Co-authored-by: John Rose Co-authored-by: Paul Sandoz Reviewed-by: ksrini, lagergren --- .../org/objectweb/asm/ByteVector.java | 8 +- .../org/objectweb/asm/ClassReader.java | 23 ++--- .../org/objectweb/asm/ClassWriter.java | 23 ++++- .../internal/org/objectweb/asm/Handle.java | 13 ++- .../org/objectweb/asm/MethodVisitor.java | 65 +++++++++--- .../org/objectweb/asm/MethodWriter.java | 98 +++++++++++++++---- .../objectweb/asm/commons/AdviceAdapter.java | 23 ++++- .../asm/commons/AnalyzerAdapter.java | 28 +++++- .../asm/commons/CodeSizeEvaluator.java | 23 ++++- .../asm/commons/GeneratorAdapter.java | 17 ++-- .../asm/commons/InstructionAdapter.java | 94 ++++++++++++++++-- .../asm/commons/JSRInlinerAdapter.java | 16 +++ .../asm/commons/LocalVariablesSorter.java | 6 ++ .../asm/commons/RemappingMethodAdapter.java | 39 +++++++- .../commons/RemappingSignatureAdapter.java | 6 +- .../asm/commons/SerialVersionUIDAdder.java | 9 +- .../asm/commons/StaticInitMerger.java | 3 +- .../asm/commons/TryCatchBlockSorter.java | 1 - .../objectweb/asm/tree/AnnotationNode.java | 5 + .../org/objectweb/asm/tree/ClassNode.java | 6 ++ .../org/objectweb/asm/tree/FieldNode.java | 8 +- .../objectweb/asm/tree/MethodInsnNode.java | 35 ++++++- .../org/objectweb/asm/tree/MethodNode.java | 38 ++++++- .../asm/tree/TypeAnnotationNode.java | 5 + .../objectweb/asm/tree/analysis/Frame.java | 9 ++ .../org/objectweb/asm/util/ASMifier.java | 41 +++++++- .../objectweb/asm/util/CheckClassAdapter.java | 17 +++- .../objectweb/asm/util/CheckFieldAdapter.java | 5 + .../asm/util/CheckMethodAdapter.java | 71 +++++++++++--- .../org/objectweb/asm/util/Printer.java | 29 +++++- .../org/objectweb/asm/util/Textifier.java | 28 ++++++ .../asm/util/TraceMethodVisitor.java | 26 ++++- .../internal/org/objectweb/asm/version.txt | 12 +-- 33 files changed, 711 insertions(+), 119 deletions(-) diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java index 0d3472bcac1..89eb6d4b640 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ByteVector.java @@ -233,11 +233,14 @@ public class ByteVector { * automatically enlarged if necessary. * * @param s - * a String. + * a String whose UTF8 encoded length must be less than 65536. * @return this byte vector. */ public ByteVector putUTF8(final String s) { int charLength = s.length(); + if (charLength > 65535) { + throw new IllegalArgumentException(); + } int len = length; if (len + 2 + charLength > data.length) { enlarge(2 + charLength); @@ -267,6 +270,9 @@ public class ByteVector { byteLength += 2; } } + if (byteLength > 65535) { + throw new IllegalArgumentException(); + } data[length] = (byte) (byteLength >>> 8); data[length + 1] = (byte) byteLength; if (length + 2 + byteLength > data.length) { diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java index 8cbc2d2c199..4f842157ac3 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java @@ -1266,7 +1266,7 @@ public class ClassReader { u += 2; // generates the first (implicit) stack map frame - if (FRAMES && (stackMap != 0 || unzip)) { + if (FRAMES && stackMap != 0) { /* * for the first explicit frame the offset is not offset_delta + 1 * but only offset_delta; setting the implicit frame offset to -1 @@ -1283,8 +1283,6 @@ public class ClassReader { if (unzip) { getImplicitFrame(context); } - } - if (FRAMES && stackMap != 0) { /* * Finds labels for UNINITIALIZED frame types. Instead of decoding * each element of the stack map table, we look for 3 consecutive @@ -1322,17 +1320,19 @@ public class ClassReader { } } - // visits the frame(s) for this offset, if any + // visits the frame for this offset, if any while (FRAMES && frame != null && (frame.offset == offset || frame.offset == -1)) { // if there is a frame for this offset, makes the visitor visit // it, and reads the next frame if there is one. - if (!zip || unzip) { - mv.visitFrame(Opcodes.F_NEW, frame.localCount, frame.local, - frame.stackCount, frame.stack); - } else if (frame.offset != -1) { - mv.visitFrame(frame.mode, frame.localDiff, frame.local, - frame.stackCount, frame.stack); + if (frame.offset != -1) { + if (!zip || unzip) { + mv.visitFrame(Opcodes.F_NEW, frame.localCount, + frame.local, frame.stackCount, frame.stack); + } else { + mv.visitFrame(frame.mode, frame.localDiff, frame.local, + frame.stackCount, frame.stack); + } } if (frameCount > 0) { stackMap = readFrame(stackMap, zip, unzip, frame); @@ -1434,6 +1434,7 @@ public class ClassReader { case ClassWriter.FIELDORMETH_INSN: case ClassWriter.ITFMETH_INSN: { int cpIndex = items[readUnsignedShort(u + 1)]; + boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; String iowner = readClass(cpIndex, c); cpIndex = items[readUnsignedShort(cpIndex + 2)]; String iname = readUTF8(cpIndex, c); @@ -1441,7 +1442,7 @@ public class ClassReader { if (opcode < Opcodes.INVOKEVIRTUAL) { mv.visitFieldInsn(opcode, iowner, iname, idesc); } else { - mv.visitMethodInsn(opcode, iowner, iname, idesc); + mv.visitMethodInsn(opcode, iowner, iname, idesc, itf); } if (opcode == Opcodes.INVOKEINTERFACE) { u += 5; diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java index d5d8fa48903..ab9dcd0dce4 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java @@ -516,12 +516,12 @@ public class ClassWriter extends ClassVisitor { * true if the maximum stack size and number of local variables * must be automatically computed. */ - private final boolean computeMaxs; + private boolean computeMaxs; /** * true if the stack map frames must be recomputed from scratch. */ - private final boolean computeFrames; + private boolean computeFrames; /** * true if the stack map tables of this class are invalid. The @@ -988,9 +988,22 @@ public class ClassWriter extends ClassVisitor { attrs.put(this, null, 0, -1, -1, out); } if (invalidFrames) { - ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); - new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES); - return cw.toByteArray(); + anns = null; + ianns = null; + attrs = null; + innerClassesCount = 0; + innerClasses = null; + bootstrapMethodsCount = 0; + bootstrapMethods = null; + firstField = null; + lastField = null; + firstMethod = null; + lastMethod = null; + computeMaxs = false; + computeFrames = true; + invalidFrames = false; + new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES); + return toByteArray(); } return out.data; } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java index f262f9a09a0..e8b2859b05d 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Handle.java @@ -78,7 +78,8 @@ public final class Handle { final int tag; /** - * The internal name of the field or method designed by this handle. + * The internal name of the class that owns the field or method designated + * by this handle. */ final String owner; @@ -105,8 +106,8 @@ public final class Handle { * {@link Opcodes#H_NEWINVOKESPECIAL} or * {@link Opcodes#H_INVOKEINTERFACE}. * @param owner - * the internal name of the field or method designed by this - * handle. + * the internal name of the class that owns the field or method + * designated by this handle. * @param name * the name of the field or method designated by this handle. * @param desc @@ -135,9 +136,11 @@ public final class Handle { } /** - * Returns the internal name of the field or method designed by this handle. + * Returns the internal name of the class that owns the field or method + * designated by this handle. * - * @return the internal name of the field or method designed by this handle. + * @return the internal name of the class that owns the field or method + * designated by this handle. */ public String getOwner() { return owner; diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java index f21519e962c..0bb1a05b805 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodVisitor.java @@ -68,11 +68,11 @@ package jdk.internal.org.objectweb.asm; * visitTryCatchBlock | visitTryCatchBlockAnnotation | * visitLocalVariable | visitLocalVariableAnnotation | * visitLineNumber )* visitMaxs ] visitEnd. In - * addition, the visitXInsn and visitLabel - * methods must be called in the sequential order of the bytecode instructions - * of the visited code, visitInsnAnnotation must be called after - * the annotated instruction, visitTryCatchBlock must be called - * before the labels passed as arguments have been visited, + * addition, the visitXInsn and visitLabel methods must + * be called in the sequential order of the bytecode instructions of the visited + * code, visitInsnAnnotation must be called after the annotated + * instruction, visitTryCatchBlock must be called before the + * labels passed as arguments have been visited, * visitTryCatchBlockAnnotation must be called after the * corresponding try catch block has been visited, and the * visitLocalVariable, visitLocalVariableAnnotation and @@ -274,13 +274,9 @@ public abstract class MethodVisitor { * compressed form (all frames must use the same format, i.e. you must not * mix expanded and compressed frames within a single method): *
    - *
  • In expanded form, all frames must have the F_NEW type, and a first - * frame corresponding to the method signature must be explicitly visited - * before the first instruction.
  • + *
  • In expanded form, all frames must have the F_NEW type.
  • *
  • In compressed form, frames are basically "deltas" from the state of - * the previous frame (the first frame, corresponding to the method's - * parameters and access flags, is implicit in this form, and must not be - * visited): + * the previous frame: *
      *
    • {@link Opcodes#F_SAME} representing frame with exactly the same * locals as the previous frame and with the empty stack.
    • @@ -296,8 +292,14 @@ public abstract class MethodVisitor { * same as the locals in the previous frame, except that the last 1-3 locals * are absent and with the empty stack (nLocals is 1, 2 or 3). *
    • {@link Opcodes#F_FULL} representing complete frame data.
    • - *
  • *
+ * + * + *
+ * In both cases the first frame, corresponding to the method's parameters + * and access flags, is implicit and must not be visited. Also, it is + * illegal to visit two or more frames for the same code location (i.e., at + * least one instruction must be visited between two calls to visitFrame). * * @param type * the type of this stack map frame. Must be @@ -466,13 +468,52 @@ public abstract class MethodVisitor { * @param desc * the method's descriptor (see {@link Type Type}). */ + @Deprecated public void visitMethodInsn(int opcode, String owner, String name, String desc) { + if (api >= Opcodes.ASM5) { + boolean itf = opcode == Opcodes.INVOKEINTERFACE; + visitMethodInsn(opcode, owner, name, desc, itf); + return; + } if (mv != null) { mv.visitMethodInsn(opcode, owner, name, desc); } } + /** + * Visits a method instruction. A method instruction is an instruction that + * invokes a method. + * + * @param opcode + * the opcode of the type instruction to be visited. This opcode + * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or + * INVOKEINTERFACE. + * @param owner + * the internal name of the method's owner class (see + * {@link Type#getInternalName() getInternalName}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link Type Type}). + * @param itf + * if the method's owner class is an interface. + */ + public void visitMethodInsn(int opcode, String owner, String name, + String desc, boolean itf) { + if (api < Opcodes.ASM5) { + if (itf != (opcode == Opcodes.INVOKEINTERFACE)) { + throw new IllegalArgumentException( + "INVOKESPECIAL/STATIC on interfaces require ASM 5"); + } + visitMethodInsn(opcode, owner, name, desc); + return; + } + if (mv != null) { + mv.visitMethodInsn(opcode, owner, name, desc, itf); + } + } + /** * Visits an invokedynamic instruction. * diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java index f59abfa7a3a..81a82804d6e 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java @@ -71,7 +71,7 @@ class MethodWriter extends MethodVisitor { /** * Pseudo access flag used to denote constructors. */ - static final int ACC_CONSTRUCTOR = 262144; + static final int ACC_CONSTRUCTOR = 0x80000; /** * Frame has exactly the same locals as the previous stack map frame and @@ -297,11 +297,6 @@ class MethodWriter extends MethodVisitor { */ private int[] previousFrame; - /** - * Index of the next element to be added in {@link #frame}. - */ - private int frameIndex; - /** * The current stack map frame. The first element contains the offset of the * instruction to which the frame corresponds, the second element is the @@ -496,6 +491,9 @@ class MethodWriter extends MethodVisitor { cw.lastMethod = this; this.cw = cw; this.access = access; + if ("".equals(name)) { + this.access |= ACC_CONSTRUCTOR; + } this.name = cw.newUTF8(name); this.desc = cw.newUTF8(desc); this.descriptor = desc; @@ -511,9 +509,6 @@ class MethodWriter extends MethodVisitor { } this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING); if (computeMaxs || computeFrames) { - if (computeFrames && "".equals(name)) { - this.access |= ACC_CONSTRUCTOR; - } // updates maxLocals int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2; if ((access & Opcodes.ACC_STATIC) != 0) { @@ -649,8 +644,11 @@ class MethodWriter extends MethodVisitor { } if (type == Opcodes.F_NEW) { + if (previousFrame == null) { + visitImplicitFirstFrame(); + } currentLocals = nLocal; - startFrame(code.length, nLocal, nStack); + int frameIndex = startFrame(code.length, nLocal, nStack); for (int i = 0; i < nLocal; ++i) { if (local[i] instanceof String) { frame[frameIndex++] = Frame.OBJECT @@ -914,9 +912,8 @@ class MethodWriter extends MethodVisitor { @Override public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc) { + final String name, final String desc, final boolean itf) { lastCodeOffset = code.length; - boolean itf = opcode == Opcodes.INVOKEINTERFACE; Item i = cw.newMethodItem(owner, name, desc, itf); int argSize = i.intVal; // Label currentBlock = this.currentBlock; @@ -954,7 +951,7 @@ class MethodWriter extends MethodVisitor { } } // adds the instruction to the bytecode of the method - if (itf) { + if (opcode == Opcodes.INVOKEINTERFACE) { if (argSize == 0) { argSize = Type.getArgumentsAndReturnSizes(desc); i.intVal = argSize; @@ -1528,8 +1525,8 @@ class MethodWriter extends MethodVisitor { } code.data[end] = (byte) Opcodes.ATHROW; // emits a frame for this unreachable block - startFrame(start, 0, 1); - frame[frameIndex++] = Frame.OBJECT + int frameIndex = startFrame(start, 0, 1); + frame[frameIndex] = Frame.OBJECT | cw.addType("java/lang/Throwable"); endFrame(); // removes the start-end range from the exception @@ -1756,7 +1753,7 @@ class MethodWriter extends MethodVisitor { } } // visits the frame and its content - startFrame(f.owner.position, nLocal, nStack); + int frameIndex = startFrame(f.owner.position, nLocal, nStack); for (i = 0; nLocal > 0; ++i, --nLocal) { t = locals[i]; frame[frameIndex++] = t; @@ -1774,6 +1771,67 @@ class MethodWriter extends MethodVisitor { endFrame(); } + /** + * Visit the implicit first frame of this method. + */ + private void visitImplicitFirstFrame() { + // There can be at most descriptor.length() + 1 locals + int frameIndex = startFrame(0, descriptor.length() + 1, 0); + if ((access & Opcodes.ACC_STATIC) == 0) { + if ((access & ACC_CONSTRUCTOR) == 0) { + frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName); + } else { + frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS; + } + } + int i = 1; + loop: while (true) { + int j = i; + switch (descriptor.charAt(i++)) { + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + frame[frameIndex++] = 1; // Opcodes.INTEGER; + break; + case 'F': + frame[frameIndex++] = 2; // Opcodes.FLOAT; + break; + case 'J': + frame[frameIndex++] = 4; // Opcodes.LONG; + break; + case 'D': + frame[frameIndex++] = 3; // Opcodes.DOUBLE; + break; + case '[': + while (descriptor.charAt(i) == '[') { + ++i; + } + if (descriptor.charAt(i) == 'L') { + ++i; + while (descriptor.charAt(i) != ';') { + ++i; + } + } + frame[frameIndex++] = Frame.OBJECT + | cw.addType(descriptor.substring(j, ++i)); + break; + case 'L': + while (descriptor.charAt(i) != ';') { + ++i; + } + frame[frameIndex++] = Frame.OBJECT + | cw.addType(descriptor.substring(j + 1, i++)); + break; + default: + break loop; + } + } + frame[1] = frameIndex - 3; + endFrame(); + } + /** * Starts the visit of a stack map frame. * @@ -1783,8 +1841,9 @@ class MethodWriter extends MethodVisitor { * the number of local variables in the frame. * @param nStack * the number of stack elements in the frame. + * @return the index of the next element to be written in this frame. */ - private void startFrame(final int offset, final int nLocal, final int nStack) { + private int startFrame(final int offset, final int nLocal, final int nStack) { int n = 3 + nLocal + nStack; if (frame == null || frame.length < n) { frame = new int[n]; @@ -1792,7 +1851,7 @@ class MethodWriter extends MethodVisitor { frame[0] = offset; frame[1] = nLocal; frame[2] = nStack; - frameIndex = 3; + return 3; } /** @@ -2110,7 +2169,8 @@ class MethodWriter extends MethodVisitor { */ final void put(final ByteVector out) { final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC; - int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE + int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED + | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR); out.putShort(access & ~mask).putShort(name).putShort(desc); if (classReaderOffset != 0) { diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java index c7d51d45b91..c07917784df 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AdviceAdapter.java @@ -442,10 +442,31 @@ public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes } } + @Deprecated @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { - mv.visitMethodInsn(opcode, owner, name, desc); + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, final String owner, + final String name, final String desc, final boolean itf) { + mv.visitMethodInsn(opcode, owner, name, desc, itf); if (constructor) { Type[] types = Type.getArgumentTypes(desc); for (int i = 0; i < types.length; i++) { diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java index 1371250da0a..e914d45134e 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/AnalyzerAdapter.java @@ -165,10 +165,15 @@ public class AnalyzerAdapter extends MethodVisitor { * @param mv * the method visitor to which this adapter delegates calls. May * be null. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public AnalyzerAdapter(final String owner, final int access, final String name, final String desc, final MethodVisitor mv) { this(Opcodes.ASM5, owner, access, name, desc, mv); + if (getClass() != AnalyzerAdapter.class) { + throw new IllegalStateException(); + } } /** @@ -331,11 +336,32 @@ public class AnalyzerAdapter extends MethodVisitor { execute(opcode, 0, desc); } + @Deprecated @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, final String owner, + final String name, final String desc, final boolean itf) { if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc); + mv.visitMethodInsn(opcode, owner, name, desc, itf); } if (this.locals == null) { labels = null; diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java index a04a643d18b..0a41b2b8af6 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/CodeSizeEvaluator.java @@ -149,9 +149,30 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { } } + @Deprecated @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, final String owner, + final String name, final String desc, final boolean itf) { if (opcode == INVOKEINTERFACE) { minSize += 5; maxSize += 5; @@ -160,7 +181,7 @@ public class CodeSizeEvaluator extends MethodVisitor implements Opcodes { maxSize += 3; } if (mv != null) { - mv.visitMethodInsn(opcode, owner, name, desc); + mv.visitMethodInsn(opcode, owner, name, desc, itf); } } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java index 7e30acbbe72..786a5b5365a 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/GeneratorAdapter.java @@ -284,10 +284,15 @@ public class GeneratorAdapter extends LocalVariablesSorter { * the method's name. * @param desc * the method's descriptor (see {@link Type Type}). + * @throws IllegalStateException + * If a subclass calls this constructor. */ public GeneratorAdapter(final MethodVisitor mv, final int access, final String name, final String desc) { this(Opcodes.ASM5, mv, access, name, desc); + if (getClass() != GeneratorAdapter.class) { + throw new IllegalStateException(); + } } /** @@ -1400,11 +1405,11 @@ public class GeneratorAdapter extends LocalVariablesSorter { * the method to be invoked. */ private void invokeInsn(final int opcode, final Type type, - final Method method) { + final Method method, final boolean itf) { String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName(); mv.visitMethodInsn(opcode, owner, method.getName(), - method.getDescriptor()); + method.getDescriptor(), itf); } /** @@ -1416,7 +1421,7 @@ public class GeneratorAdapter extends LocalVariablesSorter { * the method to be invoked. */ public void invokeVirtual(final Type owner, final Method method) { - invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method); + invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method, false); } /** @@ -1428,7 +1433,7 @@ public class GeneratorAdapter extends LocalVariablesSorter { * the constructor to be invoked. */ public void invokeConstructor(final Type type, final Method method) { - invokeInsn(Opcodes.INVOKESPECIAL, type, method); + invokeInsn(Opcodes.INVOKESPECIAL, type, method, false); } /** @@ -1440,7 +1445,7 @@ public class GeneratorAdapter extends LocalVariablesSorter { * the method to be invoked. */ public void invokeStatic(final Type owner, final Method method) { - invokeInsn(Opcodes.INVOKESTATIC, owner, method); + invokeInsn(Opcodes.INVOKESTATIC, owner, method, false); } /** @@ -1452,7 +1457,7 @@ public class GeneratorAdapter extends LocalVariablesSorter { * the method to be invoked. */ public void invokeInterface(final Type owner, final Method method) { - invokeInsn(Opcodes.INVOKEINTERFACE, owner, method); + invokeInsn(Opcodes.INVOKEINTERFACE, owner, method, true); } /** diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java index 912b622db13..4ece2dba90d 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java @@ -82,9 +82,14 @@ public class InstructionAdapter extends MethodVisitor { * * @param mv * the method visitor to which this adapter delegates calls. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public InstructionAdapter(final MethodVisitor mv) { this(Opcodes.ASM5, mv); + if (getClass() != InstructionAdapter.class) { + throw new IllegalStateException(); + } } /** @@ -536,18 +541,39 @@ public class InstructionAdapter extends MethodVisitor { } } + @Deprecated @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, final String owner, + final String name, final String desc, final boolean itf) { switch (opcode) { case Opcodes.INVOKESPECIAL: - invokespecial(owner, name, desc); + invokespecial(owner, name, desc, itf); break; case Opcodes.INVOKEVIRTUAL: - invokevirtual(owner, name, desc); + invokevirtual(owner, name, desc, itf); break; case Opcodes.INVOKESTATIC: - invokestatic(owner, name, desc); + invokestatic(owner, name, desc, itf); break; case Opcodes.INVOKEINTERFACE: invokeinterface(owner, name, desc); @@ -1014,24 +1040,78 @@ public class InstructionAdapter extends MethodVisitor { mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc); } + @Deprecated public void invokevirtual(final String owner, final String name, final String desc) { + if (api >= Opcodes.ASM5) { + invokevirtual(owner, name, desc, false); + return; + } mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc); } + public void invokevirtual(final String owner, final String name, + final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + if (itf) { + throw new IllegalArgumentException( + "INVOKEVIRTUAL on interfaces require ASM 5"); + } + invokevirtual(owner, name, desc); + return; + } + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf); + } + + @Deprecated public void invokespecial(final String owner, final String name, final String desc) { - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc); + if (api >= Opcodes.ASM5) { + invokespecial(owner, name, desc, false); + return; + } + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false); + } + + public void invokespecial(final String owner, final String name, + final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + if (itf) { + throw new IllegalArgumentException( + "INVOKESPECIAL on interfaces require ASM 5"); + } + invokespecial(owner, name, desc); + return; + } + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf); + } + + @Deprecated + public void invokestatic(final String owner, final String name, + final String desc) { + if (api < Opcodes.ASM5) { + invokestatic(owner, name, desc, false); + return; + } + mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false); } public void invokestatic(final String owner, final String name, - final String desc) { - mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc); + final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + if (itf) { + throw new IllegalArgumentException( + "INVOKESTATIC on interfaces require ASM 5"); + } + invokestatic(owner, name, desc); + return; + } + mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf); } public void invokeinterface(final String owner, final String name, final String desc) { - mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc); + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true); } public void invokedynamic(String name, String desc, Handle bsm, diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java index 1a255b7096f..e0514114e51 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/JSRInlinerAdapter.java @@ -136,11 +136,16 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { * the internal names of the method's exception classes (see * {@link Type#getInternalName() getInternalName}). May be * null. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public JSRInlinerAdapter(final MethodVisitor mv, final int access, final String name, final String desc, final String signature, final String[] exceptions) { this(Opcodes.ASM5, mv, access, name, desc, signature, exceptions); + if (getClass() != JSRInlinerAdapter.class) { + throw new IllegalStateException(); + } } /** @@ -381,6 +386,17 @@ public class JSRInlinerAdapter extends MethodNode implements Opcodes { // Use tail recursion here in the form of an outer while loop to // avoid our stack growing needlessly: index++; + + // We implicitly assumed above that execution can always fall + // through to the next instruction after a JSR. But a subroutine may + // never return, in which case the code after the JSR is unreachable + // and can be anything. In particular, it can seem to fall off the + // end of the method, so we must handle this case here (we could + // instead detect whether execution can return or not from a JSR, + // but this is more complicated). + if (index >= instructions.size()) { + return; + } } } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java index 0353c499382..5d02c53768d 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/LocalVariablesSorter.java @@ -120,10 +120,15 @@ public class LocalVariablesSorter extends MethodVisitor { * the method's descriptor (see {@link Type Type}). * @param mv * the method visitor to which this adapter delegates calls. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public LocalVariablesSorter(final int access, final String desc, final MethodVisitor mv) { this(Opcodes.ASM5, access, desc, mv); + if (getClass() != LocalVariablesSorter.class) { + throw new IllegalStateException(); + } } /** @@ -323,6 +328,7 @@ public class LocalVariablesSorter extends MethodVisitor { int local = newLocalMapping(type); setLocalType(local, type); setFrameLocal(local, t); + changed = true; return local; } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java index 319d9dedc7e..d5493a1b1b5 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingMethodAdapter.java @@ -148,12 +148,41 @@ public class RemappingMethodAdapter extends LocalVariablesSorter { remapper.mapDesc(desc)); } + @Deprecated @Override - public void visitMethodInsn(int opcode, String owner, String name, - String desc) { - super.visitMethodInsn(opcode, remapper.mapType(owner), - remapper.mapMethodName(owner, name, desc), - remapper.mapMethodDesc(desc)); + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(int opcode, String owner, String name, + String desc, boolean itf) { + // Calling super.visitMethodInsn requires to call the correct version + // depending on this.api (otherwise infinite loops can occur). To + // simplify and to make it easier to automatically remove the backward + // compatibility code, we inline the code of the overridden method here. + // IMPORTANT: THIS ASSUMES THAT visitMethodInsn IS NOT OVERRIDDEN IN + // LocalVariableSorter. + if (mv != null) { + mv.visitMethodInsn(opcode, remapper.mapType(owner), + remapper.mapMethodName(owner, name, desc), + remapper.mapMethodDesc(desc), itf); + } } @Override diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java index 458ee69b1ff..3b8ab02a3f1 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/RemappingSignatureAdapter.java @@ -95,10 +95,12 @@ public class RemappingSignatureAdapter extends SignatureVisitor { @Override public void visitInnerClassType(String name) { + String remappedOuter = remapper.mapType(className) + '$'; className = className + '$' + name; String remappedName = remapper.mapType(className); - v.visitInnerClassType(remappedName.substring(remappedName - .lastIndexOf('$') + 1)); + int index = remappedName.startsWith(remappedOuter) ? remappedOuter + .length() : remappedName.lastIndexOf('$') + 1; + v.visitInnerClassType(remappedName.substring(index)); } @Override diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java index 4050d0ce402..de8915125ff 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java @@ -195,9 +195,14 @@ public class SerialVersionUIDAdder extends ClassVisitor { * @param cv * a {@link ClassVisitor} to which this visitor will delegate * calls. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public SerialVersionUIDAdder(final ClassVisitor cv) { this(Opcodes.ASM5, cv); + if (getClass() != SerialVersionUIDAdder.class) { + throw new IllegalStateException(); + } } /** @@ -218,7 +223,7 @@ public class SerialVersionUIDAdder extends ClassVisitor { } // ------------------------------------------------------------------------ - // Overriden methods + // Overridden methods // ------------------------------------------------------------------------ /* @@ -234,7 +239,7 @@ public class SerialVersionUIDAdder extends ClassVisitor { if (computeSVUID) { this.name = name; this.access = access; - this.interfaces = interfaces; + this.interfaces = Arrays.copyOf(interfaces, interfaces.length); } super.visit(version, access, name, signature, superName, interfaces); diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java index 3514d090787..2f2f3b6ddcb 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/StaticInitMerger.java @@ -107,7 +107,8 @@ public class StaticInitMerger extends ClassVisitor { if (clinit == null) { clinit = cv.visitMethod(a, name, desc, null, null); } - clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc); + clinit.visitMethodInsn(Opcodes.INVOKESTATIC, this.name, n, desc, + false); } else { mv = cv.visitMethod(access, name, desc, signature, exceptions); } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java index 0b2be355877..39c2bf37904 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/TryCatchBlockSorter.java @@ -66,7 +66,6 @@ import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.tree.MethodNode; import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode; -import jdk.internal.org.objectweb.asm.tree.TypeAnnotationNode; /** * A {@link MethodVisitor} adapter to sort the exception handlers. The handlers diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java index 57b88f1b11f..b67ea38591a 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/AnnotationNode.java @@ -96,9 +96,14 @@ public class AnnotationNode extends AnnotationVisitor { * * @param desc * the class descriptor of the annotation class. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public AnnotationNode(final String desc) { this(Opcodes.ASM5, desc); + if (getClass() != AnnotationNode.class) { + throw new IllegalStateException(); + } } /** diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java index cb70518aa93..39334641754 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/ClassNode.java @@ -216,9 +216,15 @@ public class ClassNode extends ClassVisitor { * Constructs a new {@link ClassNode}. Subclasses must not use this * constructor. Instead, they must use the {@link #ClassNode(int)} * version. + * + * @throws IllegalStateException + * If a subclass calls this constructor. */ public ClassNode() { this(Opcodes.ASM5); + if (getClass() != ClassNode.class) { + throw new IllegalStateException(); + } } /** diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java index a155d2c1b80..cc79a5815cb 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/FieldNode.java @@ -168,16 +168,20 @@ public class FieldNode extends FieldVisitor { * null if the field does not have an initial value, * must be an {@link Integer}, a {@link Float}, a {@link Long}, a * {@link Double} or a {@link String}. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public FieldNode(final int access, final String name, final String desc, final String signature, final Object value) { this(Opcodes.ASM5, access, name, desc, signature, value); + if (getClass() != FieldNode.class) { + throw new IllegalStateException(); + } } /** * Constructs a new {@link FieldNode}. Subclasses must not use this - * constructor. Instead, they must use the - * {@link #FieldNode(int, int, String, String, String, Object)} version. + * constructor. * * @param api * the ASM API version implemented by this visitor. Must be one diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java index 6f6d5dc4453..2f61df3b517 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodInsnNode.java @@ -61,6 +61,7 @@ package jdk.internal.org.objectweb.asm.tree; import java.util.Map; import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; /** * A node that represents a method instruction. A method instruction is an @@ -86,6 +87,11 @@ public class MethodInsnNode extends AbstractInsnNode { */ public String desc; + /** + * If the method's owner class if an interface. + */ + public boolean itf; + /** * Constructs a new {@link MethodInsnNode}. * @@ -102,12 +108,37 @@ public class MethodInsnNode extends AbstractInsnNode { * @param desc * the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). */ + @Deprecated public MethodInsnNode(final int opcode, final String owner, final String name, final String desc) { + this(opcode, owner, name, desc, opcode == Opcodes.INVOKEINTERFACE); + } + + /** + * Constructs a new {@link MethodInsnNode}. + * + * @param opcode + * the opcode of the type instruction to be constructed. This + * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or + * INVOKEINTERFACE. + * @param owner + * the internal name of the method's owner class (see + * {@link jdk.internal.org.objectweb.asm.Type#getInternalName() + * getInternalName}). + * @param name + * the method's name. + * @param desc + * the method's descriptor (see {@link jdk.internal.org.objectweb.asm.Type}). + * @param itf + * if the method's owner class is an interface. + */ + public MethodInsnNode(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { super(opcode); this.owner = owner; this.name = name; this.desc = desc; + this.itf = itf; } /** @@ -128,11 +159,11 @@ public class MethodInsnNode extends AbstractInsnNode { @Override public void accept(final MethodVisitor mv) { - mv.visitMethodInsn(opcode, owner, name, desc); + mv.visitMethodInsn(opcode, owner, name, desc, itf); } @Override public AbstractInsnNode clone(final Map labels) { - return new MethodInsnNode(opcode, owner, name, desc); + return new MethodInsnNode(opcode, owner, name, desc, itf); } } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java index 072d549265c..dfd58a0fe1f 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java @@ -71,7 +71,6 @@ import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; import jdk.internal.org.objectweb.asm.TypePath; -import jdk.internal.org.objectweb.asm.TypeReference; /** * A node that represents a method. @@ -245,9 +244,15 @@ public class MethodNode extends MethodVisitor { * Constructs an uninitialized {@link MethodNode}. Subclasses must not * use this constructor. Instead, they must use the * {@link #MethodNode(int)} version. + * + * @throws IllegalStateException + * If a subclass calls this constructor. */ public MethodNode() { this(Opcodes.ASM5); + if (getClass() != MethodNode.class) { + throw new IllegalStateException(); + } } /** @@ -281,10 +286,15 @@ public class MethodNode extends MethodVisitor { * the internal names of the method's exception classes (see * {@link Type#getInternalName() getInternalName}). May be * null. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public MethodNode(final int access, final String name, final String desc, final String signature, final String[] exceptions) { this(Opcodes.ASM5, access, name, desc, signature, exceptions); + if (getClass() != MethodNode.class) { + throw new IllegalStateException(); + } } /** @@ -461,12 +471,27 @@ public class MethodNode extends MethodVisitor { instructions.add(new FieldInsnNode(opcode, owner, name, desc)); } + @Deprecated @Override - public void visitMethodInsn(final int opcode, final String owner, - final String name, final String desc) { + public void visitMethodInsn(int opcode, String owner, String name, + String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } instructions.add(new MethodInsnNode(opcode, owner, name, desc)); } + @Override + public void visitMethodInsn(int opcode, String owner, String name, + String desc, boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf)); + } + @Override public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { @@ -696,6 +721,12 @@ public class MethodNode extends MethodVisitor { && insn.invisibleTypeAnnotations.size() > 0) { throw new RuntimeException(); } + if (insn instanceof MethodInsnNode) { + boolean itf = ((MethodInsnNode) insn).itf; + if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) { + throw new RuntimeException(); + } + } } if (visibleLocalVariableAnnotations != null && visibleLocalVariableAnnotations.size() > 0) { @@ -705,7 +736,6 @@ public class MethodNode extends MethodVisitor { && invisibleLocalVariableAnnotations.size() > 0) { throw new RuntimeException(); } - } } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java index c9e21d8c5be..641dca1c17d 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/TypeAnnotationNode.java @@ -94,10 +94,15 @@ public class TypeAnnotationNode extends AnnotationNode { * null if the annotation targets 'typeRef' as a whole. * @param desc * the class descriptor of the annotation class. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public TypeAnnotationNode(final int typeRef, final TypePath typePath, final String desc) { this(Opcodes.ASM5, typeRef, typePath, desc); + if (getClass() != TypeAnnotationNode.class) { + throw new IllegalStateException(); + } } /** diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java index 2d9434fc22e..f6b8db3ddfb 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java @@ -162,6 +162,15 @@ public class Frame { return locals; } + /** + * Returns the maximum stack size of this frame. + * + * @return the maximum stack size of this frame. + */ + public int getMaxStackSize() { + return values.length - locals; + } + /** * Returns the value of the given local variable. * diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java index 6b6bd4dc6bb..a9487e16f5e 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java @@ -113,9 +113,15 @@ public class ASMifier extends Printer { * Constructs a new {@link ASMifier}. Subclasses must not use this * constructor. Instead, they must use the * {@link #ASMifier(int, String, int)} version. + * + * @throws IllegalStateException + * If a subclass calls this constructor. */ public ASMifier() { this(Opcodes.ASM5, "cw", 0); + if (getClass() != ASMifier.class) { + throw new IllegalStateException(); + } } /** @@ -483,8 +489,9 @@ public class ASMifier extends Printer { @Override public void visitParameter(String parameterName, int access) { buf.setLength(0); - buf.append(name).append(".visitParameter(").append(parameterName) - .append(", "); + buf.append(name).append(".visitParameter("); + appendString(buf, parameterName); + buf.append(", "); appendAccess(access); text.add(buf.append(");\n").toString()); } @@ -639,9 +646,30 @@ public class ASMifier extends Printer { text.add(buf.toString()); } + @Deprecated @Override public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, + opcode == Opcodes.INVOKEINTERFACE); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, desc, itf); + return; + } + doVisitMethodInsn(opcode, owner, name, desc, itf); + } + + private void doVisitMethodInsn(final int opcode, final String owner, + final String name, final String desc, final boolean itf) { buf.setLength(0); buf.append(this.name).append(".visitMethodInsn(") .append(OPCODES[opcode]).append(", "); @@ -650,6 +678,8 @@ public class ASMifier extends Printer { appendConstant(name); buf.append(", "); appendConstant(desc); + buf.append(", "); + buf.append(itf ? "true" : "false"); buf.append(");\n"); text.add(buf.toString()); } @@ -1076,6 +1106,13 @@ public class ASMifier extends Printer { buf.append("ACC_DEPRECATED"); first = false; } + if ((access & Opcodes.ACC_MANDATED) != 0) { + if (!first) { + buf.append(" + "); + } + buf.append("ACC_MANDATED"); + first = false; + } if (first) { buf.append('0'); } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java index ad29ab964a7..5105db7f9c2 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java @@ -246,7 +246,7 @@ public class CheckClassAdapter extends ClassVisitor { List interfaces = new ArrayList(); for (Iterator i = cn.interfaces.iterator(); i.hasNext();) { - interfaces.add(Type.getObjectType(i.next().toString())); + interfaces.add(Type.getObjectType(i.next())); } for (int i = 0; i < methods.size(); ++i) { @@ -359,9 +359,14 @@ public class CheckClassAdapter extends ClassVisitor { * false to not perform any data flow check (see * {@link CheckMethodAdapter}). This option requires valid * maxLocals and maxStack values. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow) { this(Opcodes.ASM5, cv, checkDataFlow); + if (getClass() != CheckClassAdapter.class) { + throw new IllegalStateException(); + } } /** @@ -471,7 +476,15 @@ public class CheckClassAdapter extends ClassVisitor { CheckMethodAdapter.checkInternalName(outerName, "outer class name"); } if (innerName != null) { - CheckMethodAdapter.checkIdentifier(innerName, "inner class name"); + int start = 0; + while (start < innerName.length() + && Character.isDigit(innerName.charAt(start))) { + start++; + } + if (start == 0 || start < innerName.length()) { + CheckMethodAdapter.checkIdentifier(innerName, start, -1, + "inner class name"); + } } checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java index b09559c0d8a..e0857bf06b3 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckFieldAdapter.java @@ -79,9 +79,14 @@ public class CheckFieldAdapter extends FieldVisitor { * * @param fv * the field visitor to which this adapter must delegate calls. + * @throws IllegalStateException + * If a subclass calls this constructor. */ public CheckFieldAdapter(final FieldVisitor fv) { this(Opcodes.ASM5, fv); + if (getClass() != CheckFieldAdapter.class) { + throw new IllegalStateException(); + } } /** diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java index b59709890f4..0716debae62 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckMethodAdapter.java @@ -142,11 +142,6 @@ public class CheckMethodAdapter extends MethodVisitor { */ private Set