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