-
Bug
-
Resolution: Fixed
-
P3
-
19
-
b25
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8302223 | 17.0.8-oracle | Jorn Vernee | P3 | Resolved | Fixed | b01 |
JDK-8301860 | 17.0.7 | Yuri Nesterenko | P3 | Resolved | Fixed | b01 |
There's currently a check in the jar validator that checks if a class file in a versioned directory is of a greater version than the class file of the same class in the 'default' section of the jar. This happens in `FingerPrint::isCompatibleVersion`.
This rejects for instance a case where a Java 19 class file has a versioned class file for java 17:
entry: META-INF/versions/17/Lib.class, has a class version incompatible with an earlier version
The 'version' that is used by the check comes from ASM, and is a mix of the major and minor version fused into a single int. However, this check doesn't seem to account for preview versions, which change the minor in such a way that the 'version' will appear negative, and will allow the above check to pass, seemingly erroneously.
I think this check was only ever designed to compare major versions, so we can fix this issue by extracting just the major version bits from the 'version' value given by ASM.
Here is a full reproducer that demonstrates the issue. I have 2 versions of the same class:
src/17/Lib.java:
public class Lib {
public static void method() {
System.out.println("java 17");
}
}
src/19/Lib.java:
public class Lib {
public static void method() {
System.out.println("java 19");
}
}
Compiled into a jar as follows (resulting in an error):
$ javac --release 19 -d classes/19 ./src/19/Lib.java
$ javac --release 17 -d classes/17 ./src/17/Lib.java
$ jar --create --file lib.jar -C classes/19 Lib.class --release 17 -C classes/17 Lib.class
entry: META-INF/versions/17/Lib.class, has a class version incompatible with an earlier version
invalid multi-release jar file lib.jar deleted
However, if I modify src/19/Lib.java to reference a preview API:
public class Lib {
public static void method() {
System.out.println("java 19");
java.lang.foreign.Linker.nativeLinker();
}
}
And then recompile the jar:
$ javac --enable-preview --release 19 -d classes/19 .\src\19\Lib.java
Note: .\src\19\Lib.java uses preview features of Java SE 19.
Note: Recompile with -Xlint:preview for details.
$ jar --create --file lib.jar -C classes/19 Lib.class --release 17 -C classes/17 Lib.class
I don't receive any error from the jar validator (due to the reasons outlined above). I believe that is a bug.
This rejects for instance a case where a Java 19 class file has a versioned class file for java 17:
entry: META-INF/versions/17/Lib.class, has a class version incompatible with an earlier version
The 'version' that is used by the check comes from ASM, and is a mix of the major and minor version fused into a single int. However, this check doesn't seem to account for preview versions, which change the minor in such a way that the 'version' will appear negative, and will allow the above check to pass, seemingly erroneously.
I think this check was only ever designed to compare major versions, so we can fix this issue by extracting just the major version bits from the 'version' value given by ASM.
Here is a full reproducer that demonstrates the issue. I have 2 versions of the same class:
src/17/Lib.java:
public class Lib {
public static void method() {
System.out.println("java 17");
}
}
src/19/Lib.java:
public class Lib {
public static void method() {
System.out.println("java 19");
}
}
Compiled into a jar as follows (resulting in an error):
$ javac --release 19 -d classes/19 ./src/19/Lib.java
$ javac --release 17 -d classes/17 ./src/17/Lib.java
$ jar --create --file lib.jar -C classes/19 Lib.class --release 17 -C classes/17 Lib.class
entry: META-INF/versions/17/Lib.class, has a class version incompatible with an earlier version
invalid multi-release jar file lib.jar deleted
However, if I modify src/19/Lib.java to reference a preview API:
public class Lib {
public static void method() {
System.out.println("java 19");
java.lang.foreign.Linker.nativeLinker();
}
}
And then recompile the jar:
$ javac --enable-preview --release 19 -d classes/19 .\src\19\Lib.java
Note: .\src\19\Lib.java uses preview features of Java SE 19.
Note: Recompile with -Xlint:preview for details.
$ jar --create --file lib.jar -C classes/19 Lib.class --release 17 -C classes/17 Lib.class
I don't receive any error from the jar validator (due to the reasons outlined above). I believe that is a bug.
- backported by
-
JDK-8301860 jar validator doesn't account for minor class file version
-
- Resolved
-
-
JDK-8302223 jar validator doesn't account for minor class file version
-
- Resolved
-
- duplicates
-
JDK-8296119 jar tool validation with MR-JAR does not work with classes compiled with preview features enabled
-
- Closed
-
- links to
-
Commit openjdk/jdk17u-dev/4ab869e9
-
Commit openjdk/jdk/faf48e61
-
Review openjdk/jdk17u-dev/1132
-
Review openjdk/jdk/11153
(2 links to)