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

Karen Kinnear karen.kinnear at oracle.com
Thu Nov 13 14:54:14 UTC 2014


Yumin,

If you run -XX:+AbortVMOnException=java.lang.ClassCircularityError and -XX:+ShowMessageBoxOnError - you can attach a debugger
with the correct stack trace.

My notes below show a way to run a faster test script loop - i.e. see the earlier attached rerun.csh script - that way you can just run
the test, not the recompile etc. each time, and you can add your flags. Hopefully that will make it fail sooner.

hth,
Karen

On Nov 13, 2014, at 1:52 AM, Yumin Qi wrote:

> Thanks, Karen
> 
>  Now I have a standalone tests which easy to reproduce. I am trying to set debugger to trace the problem. While, I will  try the suggested fix from you too.
>  When set AbortVMOnException, it is late for debugger to attach since the execution goes to abort. Currently not easy run single (we loop in the test script) time to fail.
> 
>  Thanks
>  Yumin
> 
> On 11/12/2014 8:27 AM, Karen Kinnear wrote:
>> 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