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