ClassLoader.definePackage() throwing IllegalArgumentException

Alan Bateman alan.bateman at oracle.com
Mon May 19 17:20:36 UTC 2025



On 19/05/2025 15:34, Robert Stupp wrote:
> 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.

As we discussed already, this API "awkwardness" goes back to JDK 1.2 
(1998) so changing the behavior now would be risky. Hard to know how 
many custom class loaders are using this method but expanding the 
apiNote to include a snippet that catches IAE to deal with concurrent 
attempts to define the package would be okay.

As to your "all today's wishes & needs" comment. The "Package Version 
Specification" was of its time. It might be interesting to see how 
definePackage is used but I wouldn't be surprised to see the specXXX and 
implXXX parameters specified as null. Also the notion of sealed packages 
is legacy now.

-Alan


More information about the core-libs-dev mailing list