United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6949705 regression: deadlock in the DeployURLClassPath
JDK-6949705 : regression: deadlock in the DeployURLClassPath

Details
Type:
Bug
Submit Date:
2010-05-05
Status:
Resolved
Updated Date:
2010-11-04
Project Name:
JDK
Resolved Date:
2010-05-28
Component:
deploy
OS:
generic
Sub-Component:
deployment_toolkit
CPU:
generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
6u19
Fixed Versions:
6u21 (b05)

Related Reports
Relates:

Sub Tasks

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

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?
                                     
2010-05-05
EVALUATION

Do we have a testcase to reproduce this deadlock?
                                     
2010-05-11
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
                                     
2010-05-20



Hardware and Software, Engineered to Work Together