I see xml-apis.jar (2.0.2) contains:
- a javax.xml.parser package, which includes a FactoryFinder class
that's not in Java SE, and
- a javax.xml.transform package hierarchy, whose types at first glance
look identical to those in Java SE except for yet another FactoryFinder
class in javax.xml.transform.
If you put xml-apis.jar on the classpath, its javax.xml.** packages will
be ignored. The unnamed module reads the java.xml module which exports
javax.xml.** packages (assuming java.xml in the system image, of
course), so the application class loader delegates for javax.xml.**
packages to the loader responsible for the java.xml module. User code
that tries to access FactoryFinder will get a NoClassDefFoundError.
There's nothing special about JDK modules here. The same
NoClassDefFoundError would occur if the system image contained a module
exporting some package, and a JAR on the classpath contained the same
package with extra classes, and some code on the classpath tried to
access those extra classes. Since the module in the system image is
probably the rightful owner/exporter of the package, hard questions
should be asked about the provenance of the JAR on the classpath.
There has been some discussion of a jdeps-like tool that detects when a
JAR on your classpath is trying to split a JDK package:
http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-November/005227.html.
Alex
On 3/10/2016 10:27 AM, Paul Benedict wrote:
Alex, there are JARs that contain javax packages. Anyone in the web
development community knows how many people have included xml-apis in
their WEB-INF :-) only to find out it wasn't loaded or it took precedent
over the JDK versions.
Has Jigsaw introduced any restrictions here on this front? Honestly, I
think the JDK should make it illegal for the classpath to contain ANY
packages that the jdk has. Please opine when it is convenient for you.
Cheers,
Paul
On Wed, Mar 9, 2016 at 5:13 PM, Alex Buckley <alex.buck...@oracle.com
<mailto:alex.buck...@oracle.com>> wrote:
Paul, thank you for asking. The module system's treatment of the
unnamed module vis-a-vis named modules is probably the biggest
factor affecting usability of the module system. This is true almost
by definition because at JDK 9 GA the only named modules in the
world will be the JDK's while every other class will be in the
unnamed module of the application class loader.
So please, ask more questions about the unnamed module. I am
especially interested to know if anyone has JARs that contain javax
packages (or heaven forbid, sun or com.sun packages) found in the
JDK -- such JARs are a mortal danger to interop between unnamed and
named modules.
Alex
On 3/9/2016 1:47 PM, Paul Benedict wrote:
Thank you Alex. Since it's roughly the same as JDK 8, then it's
also not
worse. I defer to your explanation on that point.
Cheers,
Paul
On Wed, Mar 9, 2016 at 3:37 PM, Alex Buckley
<alex.buck...@oracle.com <mailto:alex.buck...@oracle.com>
<mailto:alex.buck...@oracle.com
<mailto:alex.buck...@oracle.com>>> wrote:
Presumably you would count the equivalent scenario on JDK 8
-- my
package A is in Alex.jar on the classpath and your package
A is in
Paul.jar on the classpath -- as a security issue too,
because some
of my classes may substitute for yours (or some of yours
for mine,
depending on how the classpath is constructed).
On JDK 9, we do the "substitution" cleanly. Package A is
not split.
That avoids one category of error (ClassCastException).
What about
poor package B that finds itself accessing a different
package A
than it was compiled with? Well, since package A is
exported by a
named module, it's reasonable to assume that the named
module "owns"
package A [*], and that the developer of package B
co-bundled some
version of package A without renaming it. Dangerous in JDK 8,
dangerous in JDK 9. (We're trying to encapsulate the
internals of a
module, which is different from trying to isolate modules
from each
other.)
[*] Advanced scenario: the named module exporting A is
actually an
automatic module which happened to co-bundle package A. By
placing
this JAR on the modulepath to form an automatic module, it
dominates
the JAR left on the classpath which also co-bundled package A.
Alex
On 3/9/2016 1:17 PM, Paul Benedict wrote:
But isn't what your proposing a security issue? Let's
say my
package A
is in the unnamed module and your package A is in a named
module. You
basically took over my code; your classes will be
substituted
for mine.
Cheers,
Paul
On Wed, Mar 9, 2016 at 2:38 PM, Alex Buckley
<alex.buck...@oracle.com
<mailto:alex.buck...@oracle.com> <mailto:alex.buck...@oracle.com
<mailto:alex.buck...@oracle.com>>
<mailto:alex.buck...@oracle.com
<mailto:alex.buck...@oracle.com>
<mailto:alex.buck...@oracle.com
<mailto:alex.buck...@oracle.com>>>> wrote:
On 3/9/2016 10:36 AM, Paul Benedict wrote:
From the doc:
"If a package is defined in both a named
module and the
unnamed
module then
the package in the unnamed module is ignored. This
preserves
reliable
configuration even in the face of the chaos of the
class path,
ensuring
that every module still reads at most one
module defining a
given package.
If, in our example above, a JAR file on the
class path
contains
a class
file named
com/foo/bar/alpha/AlphaFactory.class then
that file
will never
be loaded, since the com.foo.bar.alpha package is
exported by the
com.foo.bar module."
I would like some clarification. Correct me if
wrong, but I
think this
entire paragraph is really meant to be about the
perspective from a
modularized JAR? If a module has package A,
and the unnamed
module has
package A, then of course the module's package
A should
win.
However, if it is meant to be absolute
language, then I
disagree.
The unnamed module should be coherent among
itself. If the
unnamed module
has package B and relies on classes from
package A, it
should
still be able
to see its own package A. I don't think
modules should
be able
to impact
how the unnamed module sees itself. That's a
surprising
situation.
The unnamed module is not a root module during
resolution.
If your
main class is in the unnamed module (i.e. you did
java -jar
MyApp.jar rather than java -m MyApp), then the
module graph is
created by resolving various root modules (what
are they?
separate
discussion) and only then is the unnamed module
hooked up
to read
every module in the graph.
Hope we're OK so far.
If some named module in the graph exports package
A (more
than one
module exporting A? separate discussion), then
since the
unnamed
module reads that named module, the unnamed module
will
access A.*
types from that named module.
It's hard to imagine the unnamed module NOT
accessing A.*
types from
that named module. Primarily, we need to avoid a
split package
situation where code in the unnamed module sometimes
accesses A.*
types from the named module and sometimes from the
unnamed
module.
You might say, OK, let code in the unnamed module
exclusively access
A.* in the unnamed module rather than exclusively
access
A.* in the
named module. Then you have two problems:
1. There are issues for named modules in the same
class
loader as
the unnamed module -- such named modules MUST get
A.* from
the named
module rather than the unnamed module, and the
class loading
mechanism is incapable of switching based on
accessor. It'll be
common for named modules to exist in the same
class loader
as the
unnamed module, as modular JARs on the modulepath and
non-modular
JARs on the classpath all end up in the
application class
loader
(modular JARs as named modules; non-modular JARs
jointly as the
unnamed module).
2. While the module system is sure that package A
exists in the
named module, how would the module system possibly
know
that package
A exists in the unnamed module? Scanning every
class file
in every
non-modular JAR on the classpath at startup sounds
bad.
Alex