RFR: 8038468: java/lang/instrument/ParallelTransformerLoader.sh fails with ClassCircularityError
David Holmes
david.holmes at oracle.com
Mon Nov 3 02:39:27 UTC 2014
On 1/11/2014 9:55 AM, Yumin Qi wrote:
> Karen,
>
> Thanks for your detail message for debugging. Yes, from my debugging,
> the exception did happen in TestThread other than main thread. I have no
> idea why in the end the exception was reported in main thread.
Until that question is answered I will remain uneasy about simply
tweaking the test until it no longer fails. I would also like to know
when it started failing - Karen alludes to the possible introduction of
a new inner class at some point.
Thanks,
David
> You mention
>
> So that change to the test would be:
> in TestTransformer:
> if (loader != null) {
> if (tName.equals("TestThread")) {
> {
> loadClasses(3);
> }
> }
> return null;
> }
>
>
> The loader is the one defined in the test case, right? The system class
> loader is never null.
> I will try this change, let's see if it can work it out.
>
> Thanks
> Yumin
>
> On 10/31/2014 3:29 PM, Karen Kinnear wrote:
>> Yumin,
>>
>> From your earlier exception stack trace (many thanks) you reported:
>>
>> Exception in thread "main" java.lang.ClassCircularityError: (no - I
>> don't know why this is in thread "main")
>> sun/misc/URLClassPath$JarLoader$2
>> at sun.misc.URLClassPath$JarLoader.checkResource(URLClassPath.java:771)
>> at sun.misc.URLClassPath$JarLoader.getResource(URLClassPath.java:843)
>> at sun.misc.URLClassPath.getResource(URLClassPath.java:199)
>> at java.net.URLClassLoader$1.run(URLClassLoader.java:364)
>> at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
>> at java.security.AccessController.doPrivileged(Native Method)
>> at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
>> at java.lang.ClassLoader.loadClass(ClassLoader.java:426)
>> at java.lang.ClassLoader.loadClass(ClassLoader.java:359)
>> at java.lang.Class.forName0(Native Method)
>> at java.lang.Class.forName(Class.java:340)
>> at
>> ParallelTransformerLoaderApp.loadClasses(ParallelTransformerLoaderApp.java:83)
>>
>> at
>> ParallelTransformerLoaderApp.main(ParallelTransformerLoaderApp.java:45)
>>
>>
>> So I ran with -XX:AbortVMOnException=java.lang.ClassCircularityError
>> -XX:+ShowMessageBoxOnError to get
>> a log file and stack trace. See my instructions below on how to do that.
>>
>> I did this, attached a debugger, which didn't help enough since I
>> needed to see the java stack frames,
>> and got an hs_err_log also, so the stack traces came from the error
>> log.
>>
>> The stack trace was on Thread 2, which in the hs_err_log was
>> TestThread (which makes sense for what the test logic says).
>> See later in email for stack traces from Thread 2.
>>
>> Summary of stack trace:
>>
>> TestThread:
>> loadClasses(#) -> forName(TestClass#, URLClassLoader)
>> vm calls out to URLClassLoader.loadClass(String) which is
>> inherited from java.lang.ClassLoader.loadClass(String)
>> ... calls java.net.URLClassLoader.findClass(...) which calls
>> DoPrivileged java.net.URLClassLoader$1.run which calls
>> sun.misc.URLClassPath.getResource(name, false) which calls
>> sun.misc.URLClassPath$JarLoader.getResource which calls
>> sun.misc.URLClassPath$JarLoader.checkResource which
>> tries to call sun.misc.URLClassPath$JarLoader$2
>> - and then the transformer jumps in with loadClasses(# (which we
>> know is 3) and walks the same logic which tries to load
>> sun.misc.URLClassPath$JarLoader$2 again
>>
>> Note that in the placeholder table information that Yumin printed, the
>> circularity error is on sun.misc.URLClassPath$JarLoader$2 with the
>> null == boot loader, which
>> makes sense -- that is the appropriate defining loader, and therefore
>> the one the CFLH would intercept during the defineClass phase.
>>
>> In the sun.misc.URLClassPath.java file, in the class JarLoader, in the
>> method checkResource
>> ... return new Resource() { ... }
>> -- I do not know why that generates sun.misc.URLClassPath$JarLoader$1,
>> $2 and $3 at build time or when that was added.
>> I would guess that is when the bug started happening.
>>
>> When I have a successful run, sun.misc.URLClassPath$JarLoader$2 loads
>> before any TestClass1 loads.
>>
>> My belief is that the point of the test is to test parallel class
>> loading for URL class loaders.
>> I don't think the point is to test the bootstrap class loader, nor to
>> test bootstrapping - i.e. running the agent before
>> we have loaded sufficient classes to allow loading URLClassLoader
>> classes.
>>
>> What I suggested to Yumin that he try would be to change the test to
>> NOT intercept boot loader loads, so that
>> sun.misc.URLClassPath$JarLoader$#
>> can load which will in turn allow classes loaded by a URLClassLoader
>> subclass to load.
>>
>> So that change to the test would be:
>> in TestTransformer:
>> if (loader != null) {
>> if (tName.equals("TestThread")) {
>> {
>> loadClasses(3);
>> }
>> }
>> return null;
>> }
>> // I also suspect with that change, we can remove the sleep loop
>> Note: there was a printed message which said that the Thread "Signal
>> Dispatcher" has called transform(), which I
>> ignored, however it is good that we don't call loadClass on that
>> thread - which is part of what the sleep loop does -
>> but that would be handled by the boot loader screening above
>>
>> Alternatively we can preload the URLClassPath classes, but I don't
>> think we want to do that, or
>> we can have the agent explicitly screen on a variety of jdk
>> bootstrapping classes. But I think the cleaner
>> solution is to screen on the boot loader.
>>
>> Does that make any sense to others?
>>
>> thanks,
>> Karen
>>
>> p.s. How to run with hotspot flags (jtreg has a -show:rerun option,
>> but with a shell script in the test, this is more complex, so
>> the following should be easier):
>>
>> So what I did was run the test once for it to pass (not your script,
>> but just once with jtreg) so that it generated
>> the $DST/work directory.
>> I then created a rerun.csh script - attached - you can modify for your
>> own $DST directory.
>> I used it to be able to quickly rerun the test without the jtreg
>> framework and compile time etc. but mostly
>> to be able to actually add hotspot command-line flags.
>>
>>
>>
>>
>> p.p.s. details from the error log (let me know if you want me to
>> attach the error log to the bug report)
>>
>> note: error log shows last 10 events including:
>> Event: 0.928 loading class sun/misc/URLClassPath$JarLoader$2
>> Event: 0.928 loading class TestClass3
>> Event: 0.929 loading class TestClass3 done
>> Event: 0.929 loading class java/lang/ClassCircularityError
>> Event: 0.929 loading class java/lang/ClassCircularityError done
>>
>> TestThread
>>
>> java frames:
>>
>> j
>> sun.misc.URLClassPath$JarLoader.checkResource(Ljava/lang/String;ZLjava/util/jar/JarEntry;)Lsun/misc/Resource;+42
>>
>> j
>> sun.misc.URLClassPath$JarLoader.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;+54
>>
>> j
>> sun.misc.URLClassPath.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;+53
>>
>> j java.net.URLClassLoader$1.run()Ljava/lang/Class;+26
>> j java.net.URLClassLoader$1.run()Ljava/lang/Object;+1
>> v ~StubRoutines::call_stub
>> j
>> java.security.AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;+0
>>
>> j
>> java.net.URLClassLoader.findClass(Ljava/lang/String;)Ljava/lang/Class;+13
>> j
>> java.lang.ClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;+70
>> j java.lang.ClassLoader.loadClass(Ljava/lang/String;)Ljava/lang/Class;+3
>> v ~StubRoutines::call_stub
>> j
>> java.lang.Class.forName0(Ljava/lang/String;ZLjava/lang/ClassLoader;Ljava/lang/Class;)Ljava/lang/Class;+0
>>
>> j
>> java.lang.Class.forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;+49
>>
>> j ParallelTransformerLoaderAgent$TestTransformer.loadClasses(I)V+25
>> j
>> ParallelTransformerLoaderAgent$TestTransformer.transform(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[B)[B+81
>>
>> j
>> sun.instrument.TransformerManager.transform(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[B)[B+50
>>
>> j
>> sun.instrument.InstrumentationImpl.transform(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[BZ)[B+34
>>
>> v ~StubRoutines::call_stub
>> j
>> sun.misc.URLClassPath$JarLoader.checkResource(Ljava/lang/String;ZLjava/util/jar/JarEntry;)Lsun/misc/Resource;+42
>>
>> j
>> sun.misc.URLClassPath$JarLoader.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;+54
>>
>> j
>> sun.misc.URLClassPath.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;+53
>>
>> j java.net.URLClassLoader$1.run()Ljava/lang/Class;+26
>> j java.net.URLClassLoader$1.run()Ljava/lang/Object;+1
>> v ~StubRoutines::call_stub
>> j
>> java.security.AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;+0
>>
>> j
>> java.net.URLClassLoader.findClass(Ljava/lang/String;)Ljava/lang/Class;+13
>> j
>> java.lang.ClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;+70
>> j java.lang.ClassLoader.loadClass(Ljava/lang/String;)Ljava/lang/Class;+3
>> v ~StubRoutines::call_stub
>> j
>> java.lang.Class.forName0(Ljava/lang/String;ZLjava/lang/ClassLoader;Ljava/lang/Class;)Ljava/lang/Class;+0
>>
>> j
>> java.lang.Class.forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;+49
>>
>> j ParallelTransformerLoaderApp.loadClasses(I)V+25
>> j ParallelTransformerLoaderApp$TestThread.run()V+4
>> v ~StubRoutines::call_stub
>>
>>
>>
>> detailed frames:
>>
>> V [libjvm.so+0x760f5a] Exceptions::_throw_msg(Thread*, char const*,
>> int, Symbol*, char const*)+0x7c
>> V [libjvm.so+0xce005c]
>> SystemDictionary::resolve_instance_class_or_null(Symbol*, Handle,
>> Handle, Thread*)+0x7d8
>> V [libjvm.so+0xcde9e5] SystemDictionary::resolve_or_null(Symbol*,
>> Handle, Handle, Thread*)+0x26d
>> V [libjvm.so+0xcde435] SystemDictionary::resolve_or_fail(Symbol*,
>> Handle, Handle, bool, Thread*)+0x39
>> V [libjvm.so+0x690fbc]
>> ConstantPool::klass_at_impl(constantPoolHandle, int, Thread*)+0x3cc
>> V [libjvm.so+0x5398cb] ConstantPool::klass_at(int, Thread*)+0x55
>> V [libjvm.so+0x8b1f3c] InterpreterRuntime::_new(JavaThread*,
>> ConstantPool*, int)+0x14a
>> j
>> sun.misc.URLClassPath$JarLoader.checkResource(Ljava/lang/String;ZLjava/util/jar/JarEntry;)Lsun/misc/Resource;+42
>>
>> j
>> sun.misc.URLClassPath$JarLoader.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;+54
>>
>> j
>> sun.misc.URLClassPath.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;+53
>>
>> j java.net.URLClassLoader$1.run()Ljava/lang/Class;+26
>> j java.net.URLClassLoader$1.run()Ljava/lang/Object;+1
>> v ~StubRoutines::call_stub
>> V [libjvm.so+0x8c3060] JavaCalls::call_helper(JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*)+0x6b2
>> V [libjvm.so+0xba06bc] os::os_exception_wrapper(void (*)(JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*), JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*)+0x3a
>> V [libjvm.so+0x8c29a7] JavaCalls::call(JavaValue*, methodHandle,
>> JavaCallArguments*, Thread*)+0x7d
>> V [libjvm.so+0x972a80] JVM_DoPrivileged+0x63d
>> j
>> java.security.AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;+0
>>
>> j
>> java.net.URLClassLoader.findClass(Ljava/lang/String;)Ljava/lang/Class;+13
>> j
>> java.lang.ClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;+70
>> j java.lang.ClassLoader.loadClass(Ljava/lang/String;)Ljava/lang/Class;+3
>> v ~StubRoutines::call_stub
>> V [libjvm.so+0x8c3060] JavaCalls::call_helper(JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*)+0x6b2
>> V [libjvm.so+0xba06bc] os::os_exception_wrapper(void (*)(JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*), JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*)+0x3a
>> V [libjvm.so+0x8c29a7] JavaCalls::call(JavaValue*, methodHandle,
>> JavaCallArguments*, Thread*)+0x7d
>> V [libjvm.so+0x8c1ec7] JavaCalls::call_virtual(JavaValue*,
>> KlassHandle, Symbol*, Symbol*, JavaCallArguments*, Thread*)+0x1cb
>> V [libjvm.so+0x8c2086] JavaCalls::call_virtual(JavaValue*, Handle,
>> KlassHandle, Symbol*, Symbol*, Handle, Thread*)+0xb0
>> V [libjvm.so+0xce2096]
>> SystemDictionary::load_instance_class(Symbol*, Handle, Thread*)+0x4ea
>> V [libjvm.so+0xce00a8]
>> SystemDictionary::resolve_instance_class_or_null(Symbol*, Handle,
>> Handle, Thread*)+0x824
>> V [libjvm.so+0xcde9e5] SystemDictionary::resolve_or_null(Symbol*,
>> Handle, Handle, Thread*)+0x26d
>> V [libjvm.so+0xcde435] SystemDictionary::resolve_or_fail(Symbol*,
>> Handle, Handle, bool, Thread*)+0x39
>> V [libjvm.so+0x98c89e] find_class_from_class_loader(JNIEnv_*,
>> Symbol*, unsigned char, Handle, Handle, unsigned char, Thread*)+0x49
>> V [libjvm.so+0x96f681] JVM_FindClassFromCaller+0x39d
>> C [libjava.so+0xdfd0] Java_java_lang_Class_forName0+0x130
>> j
>> java.lang.Class.forName0(Ljava/lang/String;ZLjava/lang/ClassLoader;Ljava/lang/Class;)Ljava/lang/Class;+0
>>
>> j
>> java.lang.Class.forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;+49
>>
>> j ParallelTransformerLoaderAgent$TestTransformer.loadClasses(I)V+25
>> j
>> ParallelTransformerLoaderAgent$TestTransformer.transform(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[B)[B+81
>>
>> j
>> sun.instrument.TransformerManager.transform(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[B)[B+50
>>
>> j
>> sun.instrument.InstrumentationImpl.transform(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/Class;Ljava/security/ProtectionDomain;[BZ)[B+34
>>
>> v ~StubRoutines::call_stub
>> V [libjvm.so+0x8c3060] JavaCalls::call_helper(JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*)+0x6b2
>> V [libjvm.so+0xba06bc] os::os_exception_wrapper(void (*)(JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*), JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*)+0x3a
>> V [libjvm.so+0x8c29a7] JavaCalls::call(JavaValue*, methodHandle,
>> JavaCallArguments*, Thread*)+0x7d
>> V [libjvm.so+0x911bfb] jni_invoke_nonstatic(JNIEnv_*, JavaValue*,
>> _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)+0x3cd
>> V [libjvm.so+0x916918] jni_CallObjectMethod+0x388
>> C [libinstrument.so+0x4eb5] transformClassFile+0x1e5
>> C [libinstrument.so+0x1e06] eventHandlerClassFileLoadHook+0x96
>> V [libjvm.so+0xa04afa]
>> JvmtiClassFileLoadHookPoster::post_to_env(JvmtiEnv*, bool)+0x1a8
>> V [libjvm.so+0xa0485e]
>> JvmtiClassFileLoadHookPoster::post_all_envs()+0x8a
>> V [libjvm.so+0xa047c6] JvmtiClassFileLoadHookPoster::post()+0x18
>> V [libjvm.so+0x9fb6e1]
>> JvmtiExport::post_class_file_load_hook(Symbol*, Handle, Handle,
>> unsigned char**, unsigned char**, JvmtiCachedClassFileData**)+0x85
>> V [libjvm.so+0x5cd17d] ClassFileParser::parseClassFile(Symbol*,
>> ClassLoaderData*, Handle, KlassHandle, GrowableArray<Handle>*,
>> TempNewSymbol&, bool, Thread*)+0x2af
>> V [libjvm.so+0x5dd441] ClassFileParser::parseClassFile(Symbol*,
>> ClassLoaderData*, Handle, TempNewSymbol&, bool, Thread*)+0x95
>> V [libjvm.so+0x5daf03] ClassLoader::load_classfile(Symbol*,
>> Thread*)+0x2ed
>> V [libjvm.so+0xce1cc4]
>> SystemDictionary::load_instance_class(Symbol*, Handle, Thread*)+0x118
>> V [libjvm.so+0xce00a8]
>> SystemDictionary::resolve_instance_class_or_null(Symbol*, Handle,
>> Handle, Thread*)+0x824
>> V [libjvm.so+0xcde9e5] SystemDictionary::resolve_or_null(Symbol*,
>> Handle, Handle, Thread*)+0x26d
>> V [libjvm.so+0xcde435] SystemDictionary::resolve_or_fail(Symbol*,
>> Handle, Handle, bool, Thread*)+0x39
>> V [libjvm.so+0x690fbc]
>> ConstantPool::klass_at_impl(constantPoolHandle, int, Thread*)+0x3cc
>> V [libjvm.so+0x5398cb] ConstantPool::klass_at(int, Thread*)+0x55
>> V [libjvm.so+0x8b1f3c] InterpreterRuntime::_new(JavaThread*,
>> ConstantPool*, int)+0x14a
>> j
>> sun.misc.URLClassPath$JarLoader.checkResource(Ljava/lang/String;ZLjava/util/jar/JarEntry;)Lsun/misc/Resource;+42
>>
>> j
>> sun.misc.URLClassPath$JarLoader.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;+54
>>
>> j
>> sun.misc.URLClassPath.getResource(Ljava/lang/String;Z)Lsun/misc/Resource;+53
>>
>> j java.net.URLClassLoader$1.run()Ljava/lang/Class;+26
>> j java.net.URLClassLoader$1.run()Ljava/lang/Object;+1
>> v ~StubRoutines::call_stub
>> V [libjvm.so+0x8c3060] JavaCalls::call_helper(JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*)+0x6b2
>> V [libjvm.so+0xba06bc] os::os_exception_wrapper(void (*)(JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*), JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*)+0x3a
>> V [libjvm.so+0x8c29a7] JavaCalls::call(JavaValue*, methodHandle,
>> JavaCallArguments*, Thread*)+0x7d
>> V [libjvm.so+0x972a80] JVM_DoPrivileged+0x63d
>> j
>> java.security.AccessController.doPrivileged(Ljava/security/PrivilegedExceptionAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;+0
>>
>> j
>> java.net.URLClassLoader.findClass(Ljava/lang/String;)Ljava/lang/Class;+13
>> j
>> java.lang.ClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;+70
>> j java.lang.ClassLoader.loadClass(Ljava/lang/String;)Ljava/lang/Class;
>> v ~StubRoutines::call_stub
>> V [libjvm.so+0x8c3060] JavaCalls::call_helper(JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*)+0x6b2
>> V [libjvm.so+0xba06bc] os::os_exception_wrapper(void (*)(JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*), JavaValue*,
>> methodHandle*, JavaCallArguments*, Thread*)+0x3a
>> V [libjvm.so+0x8c29a7] JavaCalls::call(JavaValue*, methodHandle,
>> JavaCallArguments*, Thread*)+0x7d
>> V [libjvm.so+0x8c1ec7] JavaCalls::call_virtual(JavaValue*,
>> KlassHandle, Symbol*, Symbol*, JavaCallArguments*, Thread*)+0x1cb
>> V [libjvm.so+0x8c2086] JavaCalls::call_virtual(JavaValue*, Handle,
>> KlassHandle, Symbol*, Symbol*, Handle, Thread*)+0xb0
>> V [libjvm.so+0xce2096]
>> SystemDictionary::load_instance_class(Symbol*, Handle, Thread*)+0x4ea
>> V [libjvm.so+0xce00a8]
>> SystemDictionary::resolve_instance_class_or_null(Symbol*, Handle,
>> Handle, Thread*)+0x824
>> V [libjvm.so+0xcde9e5] SystemDictionary::resolve_or_null(Symbol*,
>> Handle, Handle, Thread*)+0x26d
>> V [libjvm.so+0xcde435] SystemDictionary::resolve_or_fail(Symbol*,
>> Handle, Handle, bool, Thread*)+0x39
>> V [libjvm.so+0x98c89e] find_class_from_class_loader(JNIEnv_*,
>> Symbol*, unsigned char, Handle, Handle, unsigned char, Thread*)+0x49
>> V [libjvm.so+0x96f681] JVM_FindClassFromCaller+0x39d
>> C [libjava.so+0xdfd0] Java_java_lang_Class_forName0+0x130
>> j
>> java.lang.Class.forName0(Ljava/lang/String;ZLjava/lang/ClassLoader;Ljava/lang/Class;)Ljava/lang/Class;+0
>>
>> j
>> java.lang.Class.forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;+49
>>
>> j ParallelTransformerLoaderApp.loadClasses(I)V+25
>> ...<more frames>...
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> On Oct 27, 2014, at 2:00 PM, serguei.spitsyn at oracle.com wrote:
>>
>>> Ok.
>>>
>>> Thanks, Dan!
>>> Serguei
>>>
>>>
>>> On 10/27/14 7:05 AM, Daniel D. Daugherty wrote:
>>>>> The test case was added by Dan.
>>>>> We may want to ask him to clarify the test case purpose.
>>>>> (added Dan to the to-list)
>>>> Here's the changeset that added the test:
>>>>
>>>> $ hg log -v -r bca8bf23ac59
>>>> test/java/lang/instrument/ParallelTransformerLoader.sh
>>>> changeset: 132:bca8bf23ac59
>>>> user: dcubed
>>>> date: Mon Mar 24 15:05:09 2008 -0700
>>>> files: test/java/lang/instrument/ParallelTransformerLoader.sh
>>>> test/java/lang/instrument/ParallelTransformerLoaderAgent.java
>>>> test/java/lang/instrument/ParallelTransformerLoaderApp.java
>>>> test/java/lang/instrument/TestClass1.java
>>>> test/java/lang/instrument/TestClass2.java
>>>> test/java/lang/instrument/TestClass3.java
>>>> description:
>>>> 5088398: 3/2 java.lang.instrument TCK test deadlock (test11)
>>>> Summary: Add regression test for single-threaded bootstrap classloader.
>>>> Reviewed-by: sspitsyn
>>>>
>>>>
>>>> Based on my e-mail archive for this bug and from the bug report itself,
>>>> it looks like we got this test from Wily Labs. The original bug was a
>>>> deadlock that stopped being reproducible after:
>>>>
>>>> Karen fixed the bootstrap class loader to work in parallel via:
>>>>
>>>> 4997893 4/5 Investigate allowing bootstrap loader to work in
>>>> parallel
>>>>
>>>> with that fix in place the deadlock no longer reproduces.
>>>> I'm planning to use this bug as the vehicle for getting
>>>> the test program into the INSTRUMENT_REGRESSION test suite.
>>>>
>>>> *** (#2 of 2): 2008-02-29 18:20:17 GMT+00:00 daniel.daugherty at sun.com
>>>>
>>>>
>>>> A careful reading of JDK-5088398 might reveal the intentions of this
>>>> test...
>>>>
>>>> Dan
>>>>
>>>>
>>>> On 10/24/14 5:57 PM, serguei.spitsyn at oracle.com wrote:
>>>>> Yumin,
>>>>>
>>>>> On 10/24/14 4:08 PM, Yumin Qi wrote:
>>>>>> Serguei,
>>>>>>
>>>>>> Thanks for your comments.
>>>>>> This test happens intermittently, but now it can repeat with 8/9.
>>>>>> Loading TestClass1 in main thread while loading TestClass2 in
>>>>>> TestThread in parallel. They both will call transform since
>>>>>> TestClass[1-3] are loaded via agent. When loading TestClass2, it
>>>>>> will call loading TestClass3 in TestThread.
>>>>>> Note in the main thread, for loop:
>>>>>>
>>>>>> for (int i = 0; i < kNumIterations; i++)
>>>>>> {
>>>>>> // load some classes from multiple threads
>>>>>> (this thread and one other)
>>>>>> Thread testThread = new TestThread(2);
>>>>>> testThread.start();
>>>>>> loadClasses(1);
>>>>>>
>>>>>> // log that it completed and reset for the
>>>>>> next iteration
>>>>>> testThread.join();
>>>>>> System.out.print(".");
>>>>>> ParallelTransformerLoaderAgent.generateNewClassLoader();
>>>>>> }
>>>>>>
>>>>>> The loader got renewed after testThread.join(). So both threads
>>>>>> are using the exact same class loader.
>>>>> You are right, thanks.
>>>>> It means that all three classes (TesClass1, TestClass2 and TestClass3)
>>>>> are loaded by the same class loader in each iteration.
>>>>>
>>>>> However, I see more cases when the TestClass3 gets loaded.
>>>>> It happens in a CFLH event when any other class (not TestClass*) in
>>>>> the system is loaded.
>>>>> The class loading thread can be any, not only "main" or "TestClass"
>>>>> thread.
>>>>> I suspect this test case mostly targets class loading that happens
>>>>> on other threads.
>>>>> It is because of the lines:
>>>>> // In 160_03 and older, transform() is called
>>>>> // with the "system_loader_lock" held and that
>>>>> // prevents the bootstrap class loaded from
>>>>> // running in parallel. If we add a slight
>>>>> sleep
>>>>> // delay here when the transform() call is not
>>>>> // main or TestThread, then the deadlock in
>>>>> // 160_03 and older is much more reproducible.
>>>>> if (!tName.equals("main") &&
>>>>> !tName.equals("TestThread")) {
>>>>> System.out.println("Thread '" + tName +
>>>>> "' has called transform()");
>>>>> try {
>>>>> Thread.sleep(500);
>>>>> } catch (InterruptedException ie) {
>>>>> }
>>>>> }
>>>>>
>>>>> What about the following?
>>>>>
>>>>> In the ParallelTransformerLoaderAgent.java make this change:
>>>>> if (!tName.equals("main"))
>>>>> => if (tName.equals("TestThread"))
>>>>>
>>>>> Does such updated test still failing?
>>>>>
>>>>>> After create a new class loader, next loop will use the loader.
>>>>>> This is why quite often on the stack trace we can see it resolves
>>>>>> JarLoader$2.
>>>>>>
>>>>>> I am not quite understand the test case either. Loading TestClass3
>>>>>> inside transform using the same classloader will cause call to
>>>>>> transform again and form a circle. Nonetheless, if we see
>>>>>> TestClass2 already loaded, the loop will end but that still is a
>>>>>> risk.
>>>>> In fact, I don't like that the test loads the class TestClass3 at
>>>>> the TestClass3 CFLH event.
>>>>> However, it is interesting to know why we did not see (is it the
>>>>> case?) this issue before.
>>>>> Also, it is interesting why the test stops failing with you fix
>>>>> (replacing loader with SystemClassLoader).
>>>>>
>>>>> The test case was added by Dan.
>>>>> We may want to ask him to clarify the test case purpose.
>>>>> (added Dan to the to-list)
>>>>>
>>>>> Thanks,
>>>>> Serguei
>>>>>
>>>>>> Thanks
>>>>>> Yumin
>>>>>>
>>>>>> On 10/24/2014 1:20 PM, serguei.spitsyn at oracle.com wrote:
>>>>>>> Hi Yumin,
>>>>>>>
>>>>>>> Below is some analysis to make sure I understand the test
>>>>>>> scenario correctly.
>>>>>>>
>>>>>>> The ParallelTransformerLoaderApp.main() executes a 1000 iteration
>>>>>>> loop.
>>>>>>> At each iteration it does:
>>>>>>> - creates and starts a new TestThread
>>>>>>> - loads TestClass1 with the current class loader:
>>>>>>> ParallelTransformerLoaderAgent.getClassLoader()
>>>>>>> - changes the current class loader with new one:
>>>>>>> ParallelTransformerLoaderAgent.generateNewClassLoader()
>>>>>>>
>>>>>>> The TestThread loads the TestClass2 concurrently with the main
>>>>>>> thread.
>>>>>>>
>>>>>>> At the CFLH events, the ParallelTransformerLoaderAgent does the
>>>>>>> class retransformation.
>>>>>>> If the thread loading the class is not "main", it loads the class
>>>>>>> TestClass3
>>>>>>> with the current class loader
>>>>>>> ParallelTransformerLoaderAgent.getClassLoader().
>>>>>>>
>>>>>>> Sometimes, the TestClass2 and TestClass3 are loaded by the same
>>>>>>> class loader recursively.
>>>>>>> It happens if the class loader has not been changed between
>>>>>>> loading TestClass2 and TestClass3 classes.
>>>>>>>
>>>>>>> I'm not convinced yet the test is incorrect.
>>>>>>> And it is not clear why do we get a ClassCircularityError.
>>>>>>>
>>>>>>> Please, let me know if the above understanding is wrong.
>>>>>>> I also see the reply from David and share his concerns.
>>>>>>>
>>>>>>> It is not clear if this failure is a regression.
>>>>>>> Did we observe this issue before?
>>>>>>> If - NOT then when and why had this failure started to appear?
>>>>>>>
>>>>>>> Unfortunately, it is impossible to look at the test run history
>>>>>>> at the moment.
>>>>>>> The Aurora is at a maintenance.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Serguei
>>>>>>>
>>>>>>> On 10/13/14 3:58 PM, Yumin Qi wrote:
>>>>>>>> bug: https://bugs.openjdk.java.net/browse/JDK-8038468
>>>>>>>> webrev:*http://cr.openjdk.java.net/~minqi/8038468/webrev00/
>>>>>>>>
>>>>>>>> the bug marked as confidential so post the webrev internally.
>>>>>>>>
>>>>>>>> Problem: The test case tries to load a class from the same jar
>>>>>>>> via agent in the middle of loading another class from the jar
>>>>>>>> via same class loader in same thread. The call happens in
>>>>>>>> transform which is a rare case --- in middle of loading class,
>>>>>>>> loading another class. The result is a CircularityError. When
>>>>>>>> first class is in loading, in vm we put JarLoader$2 on place
>>>>>>>> holder table, then we start the defineClass, which calls
>>>>>>>> transform, begins loading the second class so go along the same
>>>>>>>> routine for loading JarLoader$2 first, found it already in
>>>>>>>> placeholder table. A CircularityError is thrown.
>>>>>>>> Fix: The test case should not call loading class with same class
>>>>>>>> loader in same thread from same jar in 'transform' method. I
>>>>>>>> modify it loading with system class loader and we expect see
>>>>>>>> ClassNotFoundException. Detail see bug comments.
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>> Yumin *
>
More information about the jdk9-dev
mailing list