RFR: 8038468: java/lang/instrument/ParallelTransformerLoader.sh fails with ClassCircularityError

Karen Kinnear karen.kinnear at oracle.com
Wed Nov 12 16:27:54 UTC 2014


I think there are three things we need to figure out. 

1. I reproduced a problem in TestThread2. Below was the information from that and my analysis
   - all - comments on my analysis are very welcome
   - Yumin - please try the suggested test change below to see if it helps.

   - that is the only example I have seen the full details for.

2. Does the circularity error actually occur in the main thread and if so why?
   - need to catch in a debugger/hs_err file a situation in which this occurs in the main thread please.
   We need the full stack trace for this - native and java please
   - run this without the test change I suggested please
   - try to catch ClassCircularityError in the main thread

3. figure out why we we see this problem more frequently
   - I am not convinced this problem didn't already exist - the test logic has some very odd comments and workarounds which seem to imply there
   were intermittent problems from the beginning
   - that said - worth figuring out if for instance, the sun.misc.URLClassPath logic was rewritten (and when) to add $JarLoader$2
   - and looking at the history of test failure

thanks,
Karen

On Nov 2, 2014, at 9:39 PM, David Holmes wrote:

> 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