JDK-6949705 : regression: deadlock in the DeployURLClassPath
  • Type: Bug
  • Component: deploy
  • Sub-Component: deployment_toolkit
  • Affected Version: 6u19
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2010-05-05
  • Updated: 2010-11-04
  • Resolved: 2010-05-28
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6u21 b05Fixed
Related Reports
Relates :  
Description
Here is except from the stack trace:

Java stack information for the threads listed above:
> ===================================================
> "Thread-11":
> 	at java.lang.ClassLoader.loadClass(Unknown Source)
> 	- waiting to lock <0x22f02aa8> (a sun.plugin2.applet.JNLP2ClassLoader)
> 	at java.lang.ClassLoader.loadClass(Unknown Source)
> 	- locked <0x22eebef0> (a sun.plugin2.applet.JNLP2ClassLoader)
> 	at java.lang.ClassLoader.loadClass(Unknown Source)
> 	at sun.plugin2.applet.JNLP2Manager$4.run(Unknown Source)
> 	at java.lang.Thread.run(Unknown Source)
> "thread applet-com.sun.javafx.runtime.adapter.Applet-1":
> 	at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
> 	- waiting to lock <0x22eb0ff0> (a com.sun.deploy.security.DeployURLClassPath)
> 	at com.sun.deploy.security.DeployURLClassPath.getResource(Unknown Source)
> 	at sun.plugin2.applet.Plugin2ClassLoader$2.run(Unknown Source)
> 	at java.security.AccessController.doPrivileged(Native Method)
> 	at sun.plugin2.applet.Plugin2ClassLoader.findClassHelper(Unknown Source)
> 	at sun.plugin2.applet.JNLP2ClassLoader.findClass(JNLP2ClassLoader.java:318)
> 	at java.lang.ClassLoader.loadClass(Unknown Source)
> 	- locked <0x22f02aa8> (a sun.plugin2.applet.JNLP2ClassLoader)
> 	at java.lang.ClassLoader.loadClass(Unknown Source)
> 	at com.sun.javafx.runtime.adapter.Applet.init(Unknown Source)
> 	at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
> 	at java.lang.Thread.run(Unknown Source)
> "AWT-EventQueue-2":
> 	at java.lang.Class.forName0(Native Method)
> 	at java.lang.Class.forName(Unknown Source)
> 	at java.io.ObjectInputStream.resolveClass(Unknown Source)
> 	at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
> 	at java.io.ObjectInputStream.readClassDesc(Unknown Source)
> 	at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
> 	at java.io.ObjectInputStream.readObject0(Unknown Source)
> 	at java.io.ObjectInputStream.readObject(Unknown Source)
> 	at com.sun.deploy.cache.CacheEntry$12.run(Unknown Source)
> 	at java.security.AccessController.doPrivileged(Native Method)
> 	at com.sun.deploy.cache.CacheEntry.readSigners(Unknown Source)
> 	at com.sun.deploy.cache.CacheEntry.getCodeSourceCache(Unknown Source)
> 	at com.sun.deploy.cache.CacheEntry.getCodeSources(Unknown Source)
> 	at com.sun.deploy.cache.CachedJarFile.getCodeSources(Unknown Source)
> 	at com.sun.deploy.cache.DeployCacheJarAccessImpl.getCodeSources(Unknown Source)
> 	at com.sun.deploy.security.CPCallbackHandler$ParentCallback.openClassPathElement(Unknown Source)
> 	- locked <0x22eb14b0> (a com.sun.deploy.security.CPCallbackHandler$ParentCallback)
> 	at com.sun.deploy.security.DeployURLClassPath$JarLoader.getJarFile(Unknown Source)
> 	at com.sun.deploy.security.DeployURLClassPath$JarLoader.access$700(Unknown Source)
> 	at com.sun.deploy.security.DeployURLClassPath$JarLoader$1.run(Unknown Source)
> 	at java.security.AccessController.doPrivileged(Native Method)
> 	at com.sun.deploy.security.DeployURLClassPath$JarLoader.ensureOpen(Unknown Source)
> 	at com.sun.deploy.security.DeployURLClassPath$JarLoader.<init>(Unknown Source)
> 	at com.sun.deploy.security.DeployURLClassPath$3.run(Unknown Source)
> 	at java.security.AccessController.doPrivileged(Native Method)
> 	at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
> 	at com.sun.deploy.security.DeployURLClassPath.getLoader(Unknown Source)
> 	- locked <0x22eb0ff0> (a com.sun.deploy.security.DeployURLClassPath)
> 	at com.sun.deploy.security.DeployURLClassPath.access$100(Unknown Source)
> 	at com.sun.deploy.security.DeployURLClassPath$1.next(Unknown Source)
> 	at com.sun.deploy.security.DeployURLClassPath$1.hasMoreElements(Unknown Source)
> 	at java.net.URLClassLoader$3$1.run(Unknown Source)
> 	at java.security.AccessController.doPrivileged(Native Method)
> 	at java.net.URLClassLoader$3.next(Unknown Source)
> 	at java.net.URLClassLoader$3.hasMoreElements(Unknown Source)
> 	at sun.misc.CompoundEnumeration.next(Unknown Source)
> 	at sun.misc.CompoundEnumeration.hasMoreElements(Unknown Source)
> 	at sun.misc.CompoundEnumeration.next(Unknown Source)
> 	at sun.misc.CompoundEnumeration.hasMoreElements(Unknown Source)
> 	at sun.misc.Service$LazyIterator.hasNext(Unknown Source)
> 	at javax.imageio.spi.IIORegistry.registerApplicationClasspathSpis(Unknown Source)
> 	at javax.imageio.spi.IIORegistry.<init>(Unknown Source)
> 	at javax.imageio.spi.IIORegistry.getDefaultInstance(Unknown Source)
> 	at javax.imageio.ImageIO.<clinit>(Unknown Source)
> 	at com.sun.javafx.tk.desktop.AWTImageLoader.findImageReader(Unknown Source)
> 	at com.sun.javafx.tk.desktop.AWTImageLoader.readImageFromStream(Unknown Source)
> 	at com.sun.javafx.tk.desktop.AWTImageLoader.readImage(Unknown Source)
> 	at com.sun.javafx.tk.desktop.AWTImageLoader.<init>(Unknown Source)
> 	at com.sun.javafx.tk.swing.SwingToolkit.loadImage(Unknown Source)
> 	at javafx.scene.image.Image.initialize(Unknown Source)
> 	at javafx.scene.image.Image.postInit$(Unknown Source)
> 	at com.sun.javafx.runtime.FXBase.complete$(Unknown Source)
> 	at reversi.Config$Config$Script.applyDefaults$(Config.fx:13)
> 	at com.sun.javafx.runtime.FXBase.applyDefaults$(Unknown Source)
> 	at reversi.Config.<clinit>(Config.fx:1)
> 	at reversi.Main$Main$Script.initVars$(Main.fx:1)
> 	at com.sun.javafx.runtime.FXBase.initialize$(Unknown Source)
> 	at reversi.Main.<clinit>(Main.fx:1)
> 	at java.lang.Class.forName0(Native Method)
> 	at java.lang.Class.forName(Unknown Source)
> 	at com.sun.javafx.runtime.adapter.AppletStartupRoutine.run(Unknown Source)
> 	at com.sun.javafx.tk.swing.SwingToolkit$StartupRoutine.run(Unknown Source)
> 	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
> 	at java.awt.EventQueue.dispatchEvent(Unknown Source)
> 	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
> 	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
> 	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
> 	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
> 	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
> 	at java.awt.EventDispatchThread.run(Unknown Source)
> 
> Found 1 deadlock.


Full stack trace is attached.

Comments
EVALUATION Problem: Sometimes we run into deadlock when trying to reload FX applet, especially with FX applet that uses a custom progress bar. The problem is when we try to load a JAR from the cache to verify the JAR signers/certs, we read the signer/certs from the cache index file. The signer/certs are store serialized in the cache index file. When we read it back out, we need to de-serialize it. During de-serialization, we call into java.io.ObjectInputStream.resolveClass, and it triggers classloading with: Class.forName(name, false, latestUserDefinedLoader()); The latestUserDefinedLoader() is returning our plugin/javaws classloader here, causing the deadlock we see when some other threads are doing class/resource loading using the same pluing/javaws classloader. Fix: Fix is to override ObjectInputStream.resolveClass in CacheEntry, and just use: Class.forName(name, false, ClassLoader.getSystemClassLoader()); It works here because we know all the cert/signer classes can be loaded by the system classloader. Manual test case: Run this applet many times and ensure no hang is seen: http://javaweb.sfbay.sun.com/~ngthomas/mchang/reversi2.html
20-05-2010

EVALUATION Do we have a testcase to reproduce this deadlock?
11-05-2010

EVALUATION It seems that lock is happening because it is possible to get locks on classloader and classpath objects in different order (from ImageIO we start from classpath and not classloader). Perhaps DeployURLClassPath should grab lock on jnlp classloader before locking itself?
05-05-2010