aboutsummaryrefslogtreecommitdiffstats
path: root/netx/net/sourceforge/jnlp/runtime
diff options
context:
space:
mode:
authorAndrew Azores <[email protected]>2013-10-16 13:13:19 -0400
committerAndrew Azores <[email protected]>2013-10-16 13:13:19 -0400
commita8d0fefc52c821169e1c9d7be41cdeb75456dd64 (patch)
tree584807bb03aa371bc3dd0d71e804cb4a77c5b70a /netx/net/sourceforge/jnlp/runtime
parent76667d1d971e9fc9ac9840d64a38e7a06a6cfabb (diff)
Resolve multiple-applet deadlock issue in JNLPClassLoader
New lock used for synchronizing JNLPClassLoader#loadClass(String) to avoid deadlock condition when multiple applets are being loaded simultaneously. Regression test included. * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: (loadClassLock) private member for locking of loadClass method. (loadClass) synchronizes using new lock rather than instance intrinsic lock to avoid RH976833 deadlock * tests/reproducers/custom/JNLPClassLoaderDeadlock/testcases/JNLPClassLoaderDeadlockTest.java: new test for multiple applet deadlock condition * tests/reproducers/custom/JNLPClassLoaderDeadlock/resources/JNLPClassLoaderDeadlock.html: same * tests/reproducers/custom/JNLPClassLoaderDeadlock/srcs/JNLPClassLoaderDeadlock_1.java: same * tests/reproducers/custom/JNLPClassLoaderDeadlock/srcs/JNLPClassLoaderDeadlock_2.java: same * tests/reproducers/custom/JNLPClassLoaderDeadlock/srcs/Makefile: same
Diffstat (limited to 'netx/net/sourceforge/jnlp/runtime')
-rw-r--r--netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java135
1 files changed, 73 insertions, 62 deletions
diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
index c387b35..e7a080e 100644
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
@@ -205,6 +205,16 @@ public class JNLPClassLoader extends URLClassLoader {
*/
private int useCount = 0;
+ /* This Object is used as a lock on the loadClass(String) method. This method should not
+ * be entered by multiple threads simultaneously. This Object should be used for no other
+ * purpose than synchronizing the body of the loadClass(String) method. The intrinsic instance
+ * lock is not suitable for this purpose or else deadlock may occur.
+ *
+ * See bug RH976833 and the mailing list archive discussion:
+ * http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2013-September/024536.html
+ */
+ private final Object loadClassLock = new Object();
+
/**
* Create a new JNLPClassLoader from the specified file.
*
@@ -1410,88 +1420,89 @@ public class JNLPClassLoader extends URLClassLoader {
* classloader, or one of the classloaders for the JNLP file's
* extensions.
*/
- public synchronized Class<?> loadClass(String name) throws ClassNotFoundException {
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ synchronized (loadClassLock) {
+ Class<?> result = findLoadedClassAll(name);
- Class<?> result = findLoadedClassAll(name);
-
- // try parent classloader
- if (result == null) {
- try {
- ClassLoader parent = getParent();
- if (parent == null)
- parent = ClassLoader.getSystemClassLoader();
+ // try parent classloader
+ if (result == null) {
+ try {
+ ClassLoader parent = getParent();
+ if (parent == null)
+ parent = ClassLoader.getSystemClassLoader();
- return parent.loadClass(name);
- } catch (ClassNotFoundException ex) {
+ return parent.loadClass(name);
+ } catch (ClassNotFoundException ex) {
+ }
}
- }
- // filter out 'bad' package names like java, javax
- // validPackage(name);
+ // filter out 'bad' package names like java, javax
+ // validPackage(name);
- // search this and the extension loaders
- if (result == null) {
- try {
- result = loadClassExt(name);
- } catch (ClassNotFoundException cnfe) {
- // Not found in external loader either
-
- // Look in 'Class-Path' as specified in the manifest file
+ // search this and the extension loaders
+ if (result == null) {
try {
- for (String classpath: classpaths) {
- JARDesc desc;
- try {
- URL jarUrl = new URL(file.getCodeBase(), classpath);
- desc = new JARDesc(jarUrl, null, null, false, true, false, true);
- } catch (MalformedURLException mfe) {
- throw new ClassNotFoundException(name, mfe);
- }
- addNewJar(desc);
- }
-
result = loadClassExt(name);
- return result;
- } catch (ClassNotFoundException cnfe1) {
- OutputController.getLogger().log(cnfe1);
- }
-
- // As a last resort, look in any available indexes
-
- // Currently this loads jars directly from the site. We cannot cache it because this
- // call is initiated from within the applet, which does not have disk read/write permissions
- for (JarIndex index : jarIndexes) {
- // Non-generic code in sun.misc.JarIndex
- @SuppressWarnings("unchecked")
- LinkedList<String> jarList = index.get(name.replace('.', '/'));
+ } catch (ClassNotFoundException cnfe) {
+ // Not found in external loader either
- if (jarList != null) {
- for (String jarName : jarList) {
+ // Look in 'Class-Path' as specified in the manifest file
+ try {
+ for (String classpath : classpaths) {
JARDesc desc;
try {
- desc = new JARDesc(new URL(file.getCodeBase(), jarName),
- null, null, false, true, false, true);
+ URL jarUrl = new URL(file.getCodeBase(), classpath);
+ desc = new JARDesc(jarUrl, null, null, false, true, false, true);
} catch (MalformedURLException mfe) {
- throw new ClassNotFoundException(name);
- }
- try {
- addNewJar(desc);
- } catch (Exception e) {
- OutputController.getLogger().log(e);
+ throw new ClassNotFoundException(name, mfe);
}
+ addNewJar(desc);
}
- // If it still fails, let it error out
result = loadClassExt(name);
+ return result;
+ } catch (ClassNotFoundException cnfe1) {
+ OutputController.getLogger().log(cnfe1);
+ }
+
+ // As a last resort, look in any available indexes
+
+ // Currently this loads jars directly from the site. We cannot cache it because this
+ // call is initiated from within the applet, which does not have disk read/write permissions
+ for (JarIndex index : jarIndexes) {
+ // Non-generic code in sun.misc.JarIndex
+ @SuppressWarnings("unchecked")
+ LinkedList<String> jarList = index.get(name.replace('.', '/'));
+
+ if (jarList != null) {
+ for (String jarName : jarList) {
+ JARDesc desc;
+ try {
+ desc = new JARDesc(new URL(file.getCodeBase(), jarName),
+ null, null, false, true, false, true);
+ } catch (MalformedURLException mfe) {
+ throw new ClassNotFoundException(name);
+ }
+ try {
+ addNewJar(desc);
+ } catch (Exception e) {
+ OutputController.getLogger().log(e);
+ }
+ }
+
+ // If it still fails, let it error out
+ result = loadClassExt(name);
+ }
}
}
}
- }
- if (result == null) {
- throw new ClassNotFoundException(name);
- }
+ if (result == null) {
+ throw new ClassNotFoundException(name);
+ }
- return result;
+ return result;
+ }
}
/**