-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
21, 23
-
None
j.l.ClassLoader.definePackage() contains the following check, which triggers IAEs when classes from the same package are loaded against the same class loader.
{code}
if (packages.putIfAbsent(name, p) != null)
throw new IllegalArgumentException(name);
{code}
This can happen relatively easy with Weld's {{org.jboss.weld.bootstrap.ConcurrentBeanDeployer}} ([code on GitHub|https://github.com/weld/core/blob/master/impl/src/main/java/org/jboss/weld/bootstrap/ConcurrentBeanDeployer.java]).
The issue has also been reported to [Quarkus|https://github.com/quarkusio/quarkus/issues/37363].
Concurrent class loading against the same class loader and package seems legit. It looks like it can happen in every code base at any time.
The other two ConcurrentHashMaps in ClassLoader, package2certs and parallelLockMap, are not affected by this issue.
The package2cert.putIfAbsent() in checkCerts() is fine, as it only throws if the concurrently added array of certificates is different.
definePackage() could use a similar approach and replace the above code snippet with something like this:
{code}
Package ex = packages.putIfAbsent(name, p);
if (ex == null)
return p;
if (!ex.equals(p))
throw new IllegalArgumentException(name);
return ex;
{code}
and probably also enhancing the exception message.
j.l.Package however doesn't have equals/hashCode implementation, so those would have to be added as well. The problematic piece is likely to avoid the "nasty side effects" of a call to URL.equals() (the potential call to InetAddress.getByName).
When and whether the issue happens depends on the application and the performance of the system - the more cores, the higher the probability to hit this IAE.
{code}
if (packages.putIfAbsent(name, p) != null)
throw new IllegalArgumentException(name);
{code}
This can happen relatively easy with Weld's {{org.jboss.weld.bootstrap.ConcurrentBeanDeployer}} ([code on GitHub|https://github.com/weld/core/blob/master/impl/src/main/java/org/jboss/weld/bootstrap/ConcurrentBeanDeployer.java]).
The issue has also been reported to [Quarkus|https://github.com/quarkusio/quarkus/issues/37363].
Concurrent class loading against the same class loader and package seems legit. It looks like it can happen in every code base at any time.
The other two ConcurrentHashMaps in ClassLoader, package2certs and parallelLockMap, are not affected by this issue.
The package2cert.putIfAbsent() in checkCerts() is fine, as it only throws if the concurrently added array of certificates is different.
definePackage() could use a similar approach and replace the above code snippet with something like this:
{code}
Package ex = packages.putIfAbsent(name, p);
if (ex == null)
return p;
if (!ex.equals(p))
throw new IllegalArgumentException(name);
return ex;
{code}
and probably also enhancing the exception message.
j.l.Package however doesn't have equals/hashCode implementation, so those would have to be added as well. The problematic piece is likely to avoid the "nasty side effects" of a call to URL.equals() (the potential call to InetAddress.getByName).
When and whether the issue happens depends on the application and the performance of the system - the more cores, the higher the probability to hit this IAE.
- csr for
-
JDK-8350547 ClassLoader.definePackage() throws IllegalArgumentException if package already defined
-
- Draft
-
- relates to
-
JDK-6832540 IllegalArgumentException in ClassLoader.definePackage when classes are loaded in parallel
-
- Resolved
-
-
JDK-4841786 (cl) flaw in ClassLoader getPackage/definePackage API
-
- Closed
-
-
JDK-4302423 class loaders should support "local" creation of Package objects
-
- Closed
-
- links to
-
Review(master) openjdk/jdk/23737