JDK-8217215 : Enable checking/ignoring of non-conforming Class-Path entries
  • Type: CSR
  • Component: core-libs
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 13
  • Submitted: 2019-01-15
  • Updated: 2019-03-21
  • Resolved: 2019-03-16
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Stricter enforcement of the JAR Class-Path attribute requires changing the JAR spec.

Problem
-------

The JAR spec specifies that Class-Path entries must be relative URLs.  However the JDK has also accepted absolute URLs for quite some time.

There is now code in the JDK to enforce this, but it is disabled by default, for compatibility.  The JDK-8216401 fix improves compatibility of this code, so for JDK 13, we want to enable the enforcement code by default.


Solution
--------

Update the JAR spec to specify a valid Class-Path entry and reflect the new default behavior.

Some previously-working Class-Path entries could now be ignored.  Such entries would need to be updated.  To help isolate ignored Class-Path entries, setting the "jdk.net.URLClassPath.showIgnoredClassPathEntries" system property to "true" (or empty string) will print a warning message for Class-Path entries that are ignored.

Specification
-------------

JAR specification diff:

            -and interpreted by the Java 2 Platform to configure applications, class
            +and interpreted by the Java Platform to configure applications, class
    ...
             The manifest for an application can specify one or more relative URLs
             referring to the JAR files and directories for other libraries that it
             needs. These relative URLs will be treated relative to the code base
            -that the containing application was loaded from.
            +that the containing application was loaded from (the "*context JAR*").
             
             An application (or, more generally, JAR file) specifies the relative
    ...     
             At most one `Class-Path` header may be specified in a JAR file's
            -manifest..
            +manifest.
            +
            +A `Class-Path` entry is valid if the following conditions are true:
             
            -Currently, the URLs must be *relative* to the code base of the JAR file
            -for security reasons. Thus, remote optional packages will originate from
            -the same code base as the application.
            +-   It can be used to create a [`URL`](../../api/java.base/java/net/URL.html#<init>(java.net.URL,java.lang.String)),
            +    by resolving it against the context JAR���s URL.
            +
            +-   It is relative, not [absolute](../../api/java.base/java/net/URI.html#isAbsolute()),
            +    i.e. it does not contain a scheme component, except for the case when the
            +    context JAR is loaded from the file system, in which case the `file` scheme
            +    is permitted for compatibility reasons.
             
            -Each relative URL is resolved against the code base that the containing
            -application or library was loaded from. If the resulting URL is invalid
            -or refers to a resource that cannot be found then it is ignored.
            +-   The location of the JAR file or directory represented by this entry
            +    is contained within the containing directory of the context JAR.
            +    Use of "`../`" to navigate to the parent directory is not permitted,
            +    except for the case when the context JAR is loaded from the file system.
             
            -The resulting URLs are used to extend the class path for the
            -application, applet, or servlet by inserting the URLs in the class path
            -immediately following the URL of the containing JAR file. Any duplicate
            -URLs are omitted. For example, given the following class path:
            +Invalid entries are ignored.  Valid entries are resolved against the context JAR.
            +If the resulting URL is invalid or refers to a resource that cannot be found,
            +then it is ignored. Duplicate URLs are ignored.
            +
            +The resulting URLs are inserted into the class path,
            +immediately following the path of the context JAR.
            +For example, given the following class path:
    ...
            -Class-Path: x.jar a.jar
            +Class-Path: lib/x.jar a.jar
             ```
             
            -Then the resulting application class path would be the following:
            +Then the effective search path of such a `URLClassLoader` instance would be:
             
             ``` {style="MARGIN-LEFT: 40px"}
            -a.jar b.jar x.jar
            +a.jar b.jar lib/x.jar
             ```
             
             Of course, if `x.jar` had dependencies of its own then these would be

Updated JAR specification:

    Class-Path Attribute
    --------------------
    
    The manifest for an application can specify one or more relative URLs
    referring to the JAR files and directories for other libraries that it
    needs. These relative URLs will be treated relative to the code base
    that the containing application was loaded from (the "context JAR").
    
    An application (or, more generally, JAR file) specifies the relative
    URLs of the libraries that it needs via the manifest attribute
    `Class-Path`. This attribute lists the URLs to search for
    implementations of other libraries if they cannot be found on the host
    Java Virtual Machine. These relative URLs may include JAR files
    and directories for any libraries or resources needed by the
    application. Relative URLs not ending with '/' are assumed to refer to
    JAR files. For example,
    
    ``` {style="MARGIN-LEFT: 40px"}
    Class-Path: servlet.jar infobus.jar acme/beans.jar images/
    ```
    
    At most one `Class-Path` header may be specified in a JAR file's
    manifest.
    
    A `Class-Path` entry is valid if the following conditions are true:
    
    -   It can be used to create a [`URL`](../../api/java.base/java/net/URL.html#<init>(java.net.URL,java.lang.String)),
        by resolving it against the context JAR���s URL.
    
    -   It is relative, not [absolute](../../api/java.base/java/net/URI.html#isAbsolute()),
        i.e. it does not contain a scheme component, except for the case when the
        context JAR is loaded from the file system, in which case the `file` scheme
        is permitted for compatibility reasons.
    
    -   The location of the JAR file or directory represented by this entry
        is contained within the containing directory of the context JAR.
        Use of "`../`" to navigate to the parent directory is not permitted,
        except for the case when the context JAR is loaded from the file system.
    
    Invalid entries are ignored.  Valid entries are resolved against the context JAR.
    If the resulting URL is invalid or refers to a resource that cannot be found,
    then it is ignored. Duplicate URLs are ignored.

    The resulting URLs are inserted into the class path, 
    immediately following the URL of the context JAR.
    For example, given the following class path:
    
    ``` {style="MARGIN-LEFT: 40px"}
    a.jar b.jar
    ```
    
    If `b.jar` contained the following `Class-Path` manifest attribute:
    
    ``` {style="MARGIN-LEFT: 40px"}
    Class-Path: lib/x.jar a.jar
    ```
    
    Then the effective search path of such a `URLClassLoader` instance would be:
    
    ``` {style="MARGIN-LEFT: 40px"}
    a.jar b.jar lib/x.jar
    ```
    
    Of course, if `x.jar` had dependencies of its own then these would be
    added according to the same rules and so on for each subsequent URL. In
    the actual implementation, JAR file dependencies are processed lazily so
    that the JAR files are not actually opened until needed.


A new JDK-specific system property:

Setting `-Djdk.net.URLClassPath.showIgnoredClassPathEntries` or `-Djdk.net.URLClassPath.showIgnoredClassPathEntries=true` will print a warning message for Class-Path entries that are ignored.




Comments
Documenting the new property will be handled by JDK-8221267.
21-03-2019

Re-approving revised request. Is there a nature API location jdk.net.URLClassPath.showIgnoredClassPathEntries could be documented using the {@systemProperty} tag added by JDK-5076751?
16-03-2019

As noted already in the parent issue, I agree having a release note for this change is warranted. After a chat with Brent, I suggest verifying there are tests of interactions of jar file Class-Path feature with multi-release jar files (multi-release jar files is listed on another jar file's path, multi-release jar file has its own Class-Path, etc.) Moving to Approved; sorry for the delay in reviewing.
27-02-2019