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