JDK-8218268 : Javac treats Manifest Class-Path entries as Paths instead of URLs
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8,11
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2019-02-01
  • Updated: 2022-06-27
  • Resolved: 2019-12-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11 JDK 13 JDK 14
11.0.7Fixed 13.0.4Fixed 14 b27Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
Microsoft Windows [Version 10.0.17134.523]

openjdk version "13-ea" 2019-09-17
OpenJDK Runtime Environment (build 13-ea+6)
OpenJDK 64-Bit Server VM (build 13-ea+6, mixed mode, sharing)

A DESCRIPTION OF THE PROBLEM :
The Manifest Class-Path entry is specified as a relative URL.
https://docs.oracle.com/en/java/javase/11/docs/specs/jar/jar.html#class-path-attribute

But the JVM ClassLoader accepts all kinds of URLs:
- my%20dir/mylib.jar
- /C:/my%20dir/mylib.jar
- file:/C:/my%20dir/mylib.jar
- file:///C:/my%20dir/mylib.jar

The Java Compiler is treating the entries as Paths. And the behavior has changed since Java 9.

Behavior of javac 8:
- my%20dir/mylib.jar = ignored
- /C:/my%20dir/mylib.jar = ignored
- file:/C:/my%20dir/mylib.jar = ignored

Behavior of javac 9-13:
- my%20dir/mylib.jar = ignored
- /C:/my%20dir/mylib.jar = Illegal char <:> at index 2
- file:/C:/my%20dir/mylib.jar = Illegal char <:> at index 4

I expect that:
1. The Java Compiler treats the entries as URLs, according to spec.
2. The behavior of the JVM ClassLoader and the Java Compiler is equal
3. The behavior is backwards compatible
So the Java Compiler must accept all the URLs that the JVM ClassLoader also accepts nowadays.

Should be fixed in Java 11 and master.

REGRESSION : Last worked in version 8u192

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
This windows batch file demonstrates the issue.
Change the Class-Path to any other URI to see the difference. (Double % is to escape)

=====================repro.bat=====================
echo public class Hello {> Hello.java
echo 	public static String hello() {>> Hello.java
echo 		return "hello";>> Hello.java
echo 	}>> Hello.java
echo }>> Hello.java

echo public class Main {> Main.java
echo 	public static void main(String[] args) {>> Main.java
echo 		System.out.println(Hello.hello());>> Main.java
echo 	}>> Main.java
echo }>> Main.java

javac Hello.java
mkdir "Program Libs"
jar -cf "Program Libs/hello.jar" Hello.class
del Hello.class

echo Class-Path: Program%%20Libs/hello.jar > manifest.mf
jar -cfm hellocp.jar manifest.mf
del manifest.mf

javac -cp "hellocp.jar" Main.java
rem This failed. Now I add the hello.jar directly to the classpath to be able to compile
pause
javac -cp "hellocp.jar;Program Libs/hello.jar" Main.java

java -cp hellocp.jar;. Main

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
C:\javacbug>java -cp hellocp.jar;. Main
hello
ACTUAL -
C:\javacbug>javac -cp "hellocp.jar" Main.java
Main.java:3: error: cannot find symbol
                System.out.println(Hello.hello());
                                   ^
  symbol:   variable Hello
  location: class Main
1 error

C:\javacbug>javac -cp "hellocp.jar" Main.java
error: illegal argument for --class-path: Illegal char <:> at index 2: /C:/javacbug/Program%20Libs/hello.jar

C:\javacbug>javac -cp "hellocp.jar" Main.java
error: illegal argument for --class-path: Illegal char <:> at index 4: file:/C:/javacbug/Program%20Libs/hello.jar

FREQUENCY : always



Comments
Fix request (13u): I'd like to port it to 13u as well. Patch applies cleanly. Tier1 tests run OK.
03-06-2020

Having this backported to Java 11 would be really useful to prevent adding workarounds in some of the projects that are affected by this. I've opened a backport request for this issue and have a issued a RFR here https://mail.openjdk.java.net/pipermail/jdk-updates-dev/2019-December/002281.html
20-12-2019

URL: https://hg.openjdk.java.net/jdk/jdk/rev/0bd09f6d2617 User: jjg Date: 2019-12-06 21:07:40 +0000
06-12-2019

Marking noreg-trivial because the fix is small and noreg-hard because full and proper testing would involve setting up something like an http: server to help verify that http: URLs on the Class-Path are ignored.
05-12-2019

#2 is covered by JDK-8220742.
15-03-2019

The example shows various commands failing without showing the oorresponding contents of the class file. C:\javacbug>javac -cp "hellocp.jar" Main.java error: illegal argument for --class-path: Illegal char <:> at index 2: /C:/javacbug/Program%20Libs/hello.jar C:\javacbug>javac -cp "hellocp.jar" Main.java error: illegal argument for --class-path: Illegal char <:> at index 4: file:/C:/javacbug/Program%20Libs/hello.jar I believe java is correct for both of these if the given strings were indeed directly present in the Class-Path: entry. While I question the validity of the primary issue described in this bug, two subsidiary issues are noteworthy: 1. The poor error message in the examples given above in this comment: specifically the use of the option name `--class-path` when the value was (presumably) found in the Class-Path entry in the manifesto 2. The use of %20 to encode a space in the Class-Path entry. It is true that the Class-Path entry is a white-space separated list, implying that whitespace cannot be directly represented in any one entry, but the JAR spec is silent on whether percent-encoding should be supported for URLs.
28-02-2019

For comparison, see JDK-8217215.
27-02-2019

Running provided repro.bat file in all JDK: 8u192, 8u202, 11.0.2 and 13-ea+5 gives same output :: --------------------------------------------- D:\TestCases\tools\javac>repro.bat D:\TestCases\tools\javac>echo public class Hello { 1>Hello.java D:\TestCases\tools\javac>echo public static String hello() { 1>>Hello.java D:\TestCases\tools\javac>echo return "hello"; 1>>Hello.java D:\TestCases\tools\javac>echo } 1>>Hello.java D:\TestCases\tools\javac>echo } 1>>Hello.java D:\TestCases\tools\javac>echo public class Main { 1>Main.java D:\TestCases\tools\javac>echo public static void main(String[] args) { 1>>Main.java D:\TestCases\tools\javac>echo System.out.println(Hello.hello()); 1>>Main.java D:\TestCases\tools\javac>echo } 1>>Main.java D:\TestCases\tools\javac>echo } 1>>Main.java D:\TestCases\tools\javac>javac Hello.java D:\TestCases\tools\javac>mkdir "Program Libs" D:\TestCases\tools\javac>jar -cf "Program Libs/hello.jar" Hello.class D:\TestCases\tools\javac>del Hello.class D:\TestCases\tools\javac>echo Class-Path: Program%20Libs/hello.jar 1>manifest.mf D:\TestCases\tools\javac>jar -cfm hellocp.jar manifest.mf D:\TestCases\tools\javac>del manifest.mf D:\TestCases\tools\javac>javac -cp "hellocp.jar" Main.java Main.java:3: error: cannot find symbol System.out.println(Hello.hello()); ^ symbol: variable Hello location: class Main 1 error D:\TestCases\tools\javac>rem This failed. Now I add the hello.jar directly to the classpath to be able to compile D:\TestCases\tools\javac>pause Press any key to continue . . . D:\TestCases\tools\javac>javac -cp "hellocp.jar;Program Libs/hello.jar" Main.java D:\TestCases\tools\javac>java -cp hellocp.jar;. Main hello --------------------------------------------- According to the spec, an application specifies the relative URLs of the libraries that it needs via the manifest attribute Class-Path and these relative URLs may include JAR files and directories for any libraries or resources needed by the application. But here, 'javac -cp "hellocp.jar" Main.java ' is failing : hellocp.jar is a jar file specifying the the relative URL of hello.jar via manifest attribute Class-Path. Spec link for JDK 11 : https://docs.oracle.com/en/java/javase/11/docs/specs/jar/jar.html#class-path-attribute Spec link for JDK 8 : https://docs.oracle.com/javase/8/docs/technotes/guides/jar/jar.html#classpath
04-02-2019