ClassLoader.definePackage() throwing IllegalArgumentException

Robert Stupp snazy at snazy.de
Mon May 19 14:34:35 UTC 2025


Hi,

I'd like to follow up on https://bugs.openjdk.org/browse/JDK-8350547.

TL;DR java.lang.ClassLoader.definePackage() (the one taking 8 arguments) 
clearly defines that a IllegalArgumentException is thrown, "if a package 
of the given name is already defined by this class loader".

However, it seems that it's a common oversight that an IAE can be 
thrown. Examples are the CDI reference implementation ("Weld") and 
Quarkus. In other words: "naively" calling 'definePackage' without a 
retry on IAE leads to issues when defining classes in custom class 
loaders in parallel.

The CL.definePackage() API is there since Java 1.2, and I admit that my 
initial approach to change the currently observed behavior isn't going 
to fly.

I thought about adding more information to the message of the IAE thrown 
in 'definePackage()', but even this "innocent" change could break the 
observed behavior / existing code.

One option could be to add a new function 'definePackageIfNotExists()` 
to j.l.ClassLoader, which works like the existing 'definePackage()' but 
returns the existing package, if it already exists and is compatible 
with the given arguments. The downside is that it could still throw, if 
the arguments are incompatible (e.g. a different "implTitle") - so it 
might just be a less likely, but still possible way of unexpectedly 
hitting an IAE.

With 'definePackageIfNotExists()` it might be possible to deprecate 
'definePackage()', but that deprecation largely depends on the actual 
usage of it in the wild, which I do not know. I'm not sure whether such 
a deprecation can fly. And the next question would be whether it can be 
deprecated for removal ; and if yes, when could it be removed.

Actually, even a new 'definePackageIfNotExists()` could break existing 
code, in case an implementation overrides the existing 'definePackage' 
but not 'definePackageIfNotExists()`.

Another question to which I don't know the answer is whether the 7 
package attribute parameters specification/implementation 
title/version/vendor + seal-base do fit "all today's wishes & needs". 
Or: is there demand for a "better" or "more flexible" way to define a 
class/package? Or: can that API be redefined in a different way tailored 
for today's needs and wishes? And are there any that would justify such 
an effort?

Overall, I'm a bit lost on what the "best" way would be for this. Maybe 
the answer is that there is no better way yet, which is also fine. Maybe 
the only "fix" is to enhance the Javadocs and prominently highlight the 
behavior and add a "reference code snippet" how 'definePackage()' should 
be used and why.

Robert

-- 
Robert Stupp
@snazy



More information about the core-libs-dev mailing list