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




Reply via email to