6832540: IllegalArgumentException in ClassLoader.definePackage when classes are loaded in parallel
Summary: Modified to handle race condition for parallel-capable classloaders by re-trying/re-verifying package
Reviewed-by: alanb
--- a/jdk/src/share/classes/java/net/URLClassLoader.java Mon Jul 13 23:01:03 2009 +0800
+++ b/jdk/src/share/classes/java/net/URLClassLoader.java Mon Jul 13 15:14:17 2009 -0700
@@ -306,6 +306,35 @@
}
/*
+ * Retrieve the package using the specified package name.
+ * If non-null, verify the package using the specified code
+ * source and manifest.
+ */
+ private Package getAndVerifyPackage(String pkgname,
+ Manifest man, URL url) {
+ Package pkg = getPackage(pkgname);
+ if (pkg != null) {
+ // Package found, so check package sealing.
+ if (pkg.isSealed()) {
+ // Verify that code source URL is the same.
+ if (!pkg.isSealed(url)) {
+ throw new SecurityException(
+ "sealing violation: package " + pkgname + " is sealed");
+ }
+ } else {
+ // Make sure we are not attempting to seal the package
+ // at this code source URL.
+ if ((man != null) && isSealed(pkgname, man)) {
+ throw new SecurityException(
+ "sealing violation: can't seal package " + pkgname +
+ ": already loaded");
+ }
+ }
+ }
+ return pkg;
+ }
+
+ /*
* Defines a Class using the class bytes obtained from the specified
* Resource. The resulting Class must be resolved before it can be
* used.
@@ -316,32 +345,23 @@
if (i != -1) {
String pkgname = name.substring(0, i);
// Check if package already loaded.
- Package pkg = getPackage(pkgname);
Manifest man = res.getManifest();
- if (pkg != null) {
- // Package found, so check package sealing.
- if (pkg.isSealed()) {
- // Verify that code source URL is the same.
- if (!pkg.isSealed(url)) {
- throw new SecurityException(
- "sealing violation: package " + pkgname + " is sealed");
+ if (getAndVerifyPackage(pkgname, man, url) == null) {
+ try {
+ if (man != null) {
+ definePackage(pkgname, man, url);
+ } else {
+ definePackage(pkgname, null, null, null, null, null, null, null);
}
-
- } else {
- // Make sure we are not attempting to seal the package
- // at this code source URL.
- if ((man != null) && isSealed(pkgname, man)) {
- throw new SecurityException(
- "sealing violation: can't seal package " + pkgname +
- ": already loaded");
+ } catch (IllegalArgumentException iae) {
+ // parallel-capable class loaders: re-verify in case of a
+ // race condition
+ if (getAndVerifyPackage(pkgname, man, url) == null) {
+ // Should never happen
+ throw new AssertionError("Cannot find package " +
+ pkgname);
}
}
- } else {
- if (man != null) {
- definePackage(pkgname, man, url);
- } else {
- definePackage(pkgname, null, null, null, null, null, null, null);
- }
}
}
// Now read the class bytes and define the class