deadlock in initialization of instanceKlass
david.holmes at oracle.com
Thu Mar 22 18:19:52 PDT 2012
On 23/03/2012 11:13 AM, Krystal Mok wrote:
> Thanks for the quick reply. Comments inline:
> On Fri, Mar 23, 2012 at 8:09 AM, David Holmes <david.holmes at oracle.com
> <mailto:david.holmes at oracle.com>> wrote:
> Hi Kris,
> The parallel-classloading changes likely remove this problem from 7+
> I did check the value of the flag AllowParallelDefineClass, which
> defaulted to false when I ran on JDK7/HS23 and JDK8/HS24.
I think by 7 GA parallel class loaders were enabled by default - no need
for a VM flag. But my memory is rusty on this too.
> My min repro didn't use an agent. But it's easier to fall into this trap
> with an agent.
Sorry didn't look at the min repo.
> So I'm not going to stick my head in and try to "fix" this bug, since
> the problem doesn't show up in 7+ anyway.
Ok. Thanks for reporting it.
> On the int stuff: yep, I saw it. The locker object for bootstrap
> class loader is also an array, a "fake" int:
> _system_loader_lock_obj = oopFactory::new_system_objArray(0, CHECK);
> It's been like that since duke at 0...from what I can tell. Wonder why an
> array was favored over something else, say, a java.lang.Byte instance,
> which carries pretty much the same weight (in terms of object size)?
A primitive array can be created without having any classes loaded.
> Kris Mok
> On 23/03/2012 9:44 AM, Krystal Mok wrote:
> I've run into a corner case where deadlock happens during
> linking, which I think could have been avoided by patching the
> VM. It's
> mostly a JDK6-only issue, as I haven't been able to reproduce it
> on JDK7
> or JDK8.
> In the original problem, the scenario was to start a Java
> process with a
> BTrace script tracing from the beginning . As the system
> started up,
> two threads were trying to load two different classes with different
> class loaders at about the same time . Both of these class load
> operations were delegated to BTrace's agent for instrumentation,
> both threads tried to create a new instance of a class called
> "com.sun.btrace.runtime.__Instrumentor". This class was actually
> already, but not linked/initialized yet, so this was the time to
> do it.
> And then a deadlock happened: One of the threads has locked the
> class loader before trying to link the class of
> "com.sun.btrace.runtime.__Instrumentor"; where as the other
> thread went
> ahead and started linking the class of
> "com.sun.btrace.runtime.__Instrumentor" first, and for
> verification it
> needed to load new classes, which in turn needed to lock the system
> class loader.
> A simplified minimal repro of the original problem is available .
> Caveat: it may take a few runs to actually see the deadlock.
> I've had a
> better chance of reproducing it on JDK6/HS20, but harder on
> where everything seem to be faster. Haven't been able to
> reproduce it
> with JDK7/HS23 or JDK8/HS24.
> The race in this case involves locking both an instanceKlass and the
> lock object of its defining class loader. Since an instanceKlass
> isn't a
> Java-level object, Java code couldn't have locked it on its own.
> So I think there's a chance of getting around this deadlock by
> the loader before locking the instanceKlass, for places where class
> loading may happen during the period the instanceKlass is locked. Or
> perhaps the complete_exit()/reenter() dance trick.
> A pragmatic way of solving the problem is to modify the
> application code
> to get rid of the race in the first place. In this particular
> that'd be modifying BTrace, forcing the Instrumentor class to
> link early
> with a Class.forName() call. But as in the repro case, the
> problem seems
> pretty generic, and could hit innocent-looking Java code.
> (Of course, upgrading to JDK7 will get rid of the problem, too.
> good case to push for an upgrade :-)
> I haven't made a patch to fix this just yet. Any suggestions on
> it'd be worthwhile to fix it in the VM or not?
> P.S. There's a second bug. When using "jstack -l" to diagnose the
> problem, a fastdebug build of the VM hit an assertion . The
> code in
> DeadlockCycle assumed that all ObjectMonitors correspond to
> instanceOops, which is not (yet) the case. A instanceKlass or
> constantPool could also be directly locked with a ObjectMonitor, and
> that's not an instanceOop.
> I've made a patch against the current jdk8/jdk8/hotspot to fix this
> second bug .
> When the Permanent Generation removal work completes, this would no
> longer be a problem, because the klass hierarchy won't be oops
> and the klassKlass's will be gone. I can see that in Jon's
> latest patch
>  already, but there should still be some time before the work is
> complete. Meanwhile people may still run into this issue.
> Kris Mok
> https://gist.github.com/__2158975#file_deadlock_stack___trace.log <https://gist.github.com/2158975#file_deadlock_stack_trace.log>
> : https://gist.github.com/__2163070#file_test_deadlock.__java
> https://gist.github.com/__2163070#file_fix_assertion___jdk8.patch <https://gist.github.com/2163070#file_fix_assertion_jdk8.patch>
More information about the hotspot-dev