JDK-7071061 : Deadlock occurs with URLClassLoader
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux_redhat_5.0
  • CPU: x86
  • Submitted: 2011-07-26
  • Updated: 2011-08-10
  • Resolved: 2011-08-10
Related Reports
Duplicate :  
Description
A CU faces with deadlock with URLClassLoader.

CONFIGURATION:
OS :
xxxx 116 % uname -a
Linux xxxx 2.6.18-164.11.1.el5 #1 SMP Wed Jan 6 13:26:04 EST 2010 x86
_64 x86_64 x86_64 GNU/Linux

xxxx 117 % more /etc/redhat-release
Red Hat Enterprise Linux Server release 5.4 (Tikanga)

JDK : JDK7b147(32bit)/JDK6u26(32bit)

java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) Server VM (build 21.0-b17, mixed mode)

java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)


REPRODUCE:
1. Unfold attached TP2.zip
2. Go to TP2 directory
3.  In JDK6ux, launch
      java -javaagent:myagent.jar test2

    In JDK7, launch
      java -XX:+AlwaysLockClassLoader -javaagent:myagent.jar test2


You will see the following message.
<premain>
transform:StartInPremain(sun.misc.Launcher$AppClassLoader@e3a921)
transform:sun/launcher/LauncherHelper(null)
transform:java/lang/Enum(null)
transform:sun/misc/URLClassPath$FileLoader$1(null)
transform:test2(sun.misc.Launcher$AppClassLoader@e3a921)
transform:java/lang/Void(null)
transform:javax/management/MBeanInfo(null)
transform:LoadTarget1(java.net.URLClassLoader@b64078)



4. Open another console, find out the processID, and launch
   "kill -3 <processID>"

You will see an deadlock in the thread dump.
(ex. please see the attached deadlock-log-jdk6u26.txt and
deadlock-log-jdk7b147.txt. )


The CU sent some report of their investigation. Please see the comment section.

Comments
EVALUATION This is not the regular "classloader deadlock" scenario, but it is a classic deadlock scenario. The agent is invoked as part of the classloading process while the classloader is locked. The agent's transform method acquires the lock of the MyAgent class and then attempts to perform additional classloading which requires locking the classloader. The agent thread attempts to do: - lock ClassLoader 1 - lock MyAgent.class - lock ClassLoader 2 The main thread attempts to do: - lock ClassLoader 2 - lock MayAgent.class hence we get the deadlock. In Java 7 with parallel-capable loaders no classloader locking takes places and so we don't deadlock. In Java 7 with -XX:+AlwaysLockClassLoader we restore the locking of the classloader and so the deadlock returns. In Java 7 if the classloader is not parallel capable then we have the same situation as Java 6 and the deadlock is present. The only defect I see here is the lack of documentation on how to write robust agents. Agent writers need to understand how their code is executed within the classloading process and so be aware of any explicit locking they perform while doing classloading themselves. The general advice when calling out to external code (ie when the agent calls into the classloading framework) is to make "open calls" - that is to call the external code without holding any locks (ref: "Concurrent Programming in Java" by Doug Leal, "Java Concurrency in Practice" by Brian Goetz et al.)
26-07-2011