My apologies for omitting some key qualifiers in my explanation. Read
everything as a proposal to prohibit classpath jars from silently
splitting whatever packages the JDK exports. -- Thanks
On Thu, Mar 10, 2016 at 3:25 PM, Paul Benedict <pbened...@apache.org
<mailto:pbened...@apache.org>> wrote:
Alex,
For the sake of usability, however, it would be nice if the JDK
verified that jars do not contain any exported JDK packages. This
would be an RFE. I understand that in order to avoid split packages
between modules and classpath, the module version takes precedent.
For developer vs. developer code, I find that reasoning fine.
However, I really would like to treat the JDK as "special" (your
words) because in my experience, I see developers constantly
perplexed by NoClassDefFoundError when something occurred like you
just detailed.
I'd like to refer you to the Servlet 3.1 spec [1], section 10.7.2,
as an analogous concern to mine. This is the so-called "prohibited
classes" violation clause:
"As described in the Java EE license agreement, servlet containers
that are not part of a Java EE product should not allow the
application to override Java SE platform classes, such as those in
the java.* and javax.* namespaces, that Java SE does not allow to be
modified. The container should not allow applications to override or
access the container’s implementation classes."
I don't think it's good usability to let JDK packages in the
classpath go silently unchallenged and unloaded. I recommend they
are reported as an error.
[1] https://java.net/downloads/servlet-spec/Final/servlet-3_1-final.pdf
Cheers,
Paul
On Thu, Mar 10, 2016 at 2:30 PM, Alex Buckley
<alex.buck...@oracle.com <mailto:alex.buck...@oracle.com>> wrote:
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>
<mailto: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>>
<mailto: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>>>
<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
<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