JDK-8317609 : Classfile API fails to verify /jdk.jcmd/sun/tools/jstat/Alignment.class
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang.classfile
  • Affected Version: 22
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: generic
  • Submitted: 2023-10-05
  • Updated: 2024-02-27
  • Resolved: 2023-10-31
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 22
22 b22Fixed
Related Reports
Relates :  
Description
This test:

import java.nio.file.Path;
import java.util.List;
import java.util.ArrayList;
import tests.JImageValidator;

public class TestJImageValidator {
	public static void main(String[] args) throws Exception {
	    Path p = Path.of(args[0]);
	    Path modules = p.resolve("lib").resolve("modules");
	    List<String> unexpected = List.of("/java/lang/String.class");
	    List<String> expected = new ArrayList<>();
	    JImageValidator.validate(modules, expected, unexpected);
	}
}

Using the JImageValidator from https://github.com/openjdk/jdk/blob/master/test/jdk/tools/lib/tests/JImageValidator.java and then running that test on a JDK including the jdk.jcmd module like so, produces the shown exception:

java --add-opens=java.base/jdk.internal.jimage=ALL-UNNAMED --add-opens=java.base/jdk.internal.classfile=ALL-UNNAMED -cp build/linux-x86_64-server-fastdebug/test-support/jtreg_test_jdk_tools_jlink/classes/2/tools/lib:. TestJImageValidator ./build/jlink-jdk-jcmd
java.lang.IllegalArgumentException: Could not resolve class Alignment
	at java.base/jdk.internal.classfile.impl.ClassHierarchyImpl.resolve(ClassHierarchyImpl.java:75)
	at java.base/jdk.internal.classfile.impl.ClassHierarchyImpl.isInterface(ClassHierarchyImpl.java:85)
	at java.base/jdk.internal.classfile.impl.verifier.VerificationType.resolve_and_check_assignability(VerificationType.java:384)
	at java.base/jdk.internal.classfile.impl.verifier.VerificationType.is_reference_assignable_from(VerificationType.java:404)
	at java.base/jdk.internal.classfile.impl.verifier.VerificationType._is_assignable_from(VerificationType.java:334)
	at java.base/jdk.internal.classfile.impl.verifier.VerificationType.is_assignable_from(VerificationType.java:309)
	at java.base/jdk.internal.classfile.impl.verifier.VerificationFrame.pop_stack(VerificationFrame.java:161)
	at java.base/jdk.internal.classfile.impl.verifier.VerifierImpl.verify_field_instructions(VerifierImpl.java:1475)
	at java.base/jdk.internal.classfile.impl.verifier.VerifierImpl.verify_method(VerifierImpl.java:1113)
	at java.base/jdk.internal.classfile.impl.verifier.VerifierImpl.verify_method(VerifierImpl.java:284)
	at java.base/jdk.internal.classfile.impl.verifier.VerifierImpl.verify_class(VerifierImpl.java:249)
	at java.base/jdk.internal.classfile.impl.verifier.VerifierImpl.verify(VerifierImpl.java:119)
	at java.base/jdk.internal.classfile.impl.verifier.VerifierImpl.verify(VerifierImpl.java:108)
	at java.base/jdk.internal.classfile.ClassModel.verify(ClassModel.java:86)
	at tests.JImageValidator.readClass(JImageValidator.java:225)
	at tests.JImageValidator.validate(JImageValidator.java:196)
	at TestJImageValidator.main(TestJImageValidator.java:12)
/jdk.jcmd/sun/tools/jstat/Alignment.class ERROR java.io.IOException: java.lang.VerifyError: java.lang.IllegalArgumentException: Could not resolve class Alignment
Exception in thread "main" java.io.IOException: java.lang.VerifyError: java.lang.IllegalArgumentException: Could not resolve class Alignment
	at tests.JImageValidator.readClass(JImageValidator.java:230)
	at tests.JImageValidator.validate(JImageValidator.java:196)
	at TestJImageValidator.main(TestJImageValidator.java:12)
Caused by: java.lang.VerifyError: java.lang.IllegalArgumentException: Could not resolve class Alignment
	at java.base/jdk.internal.classfile.impl.verifier.VerifierImpl.verify_method(VerifierImpl.java:289)
	at java.base/jdk.internal.classfile.impl.verifier.VerifierImpl.verify_class(VerifierImpl.java:249)
	at java.base/jdk.internal.classfile.impl.verifier.VerifierImpl.verify(VerifierImpl.java:119)
	at java.base/jdk.internal.classfile.impl.verifier.VerifierImpl.verify(VerifierImpl.java:108)
	at java.base/jdk.internal.classfile.ClassModel.verify(ClassModel.java:86)
	at tests.JImageValidator.readClass(JImageValidator.java:225)
	... 2 more

The JDK image './build/jlink-jdk-jcmd' got produced with:
$ jlink --add-modules jdk.jcmd --output ./build/jlink-jdk-jcmd

Not sure what's wrong with the com.tools.jstat.Alignment.class to trigger this.
Comments
Changeset: f1e87873 Author: Adam Sotona <asotona@openjdk.org> Date: 2023-10-31 16:13:41 +0000 URL: https://git.openjdk.org/jdk/commit/f1e878739300ed37c686ba570423c6f8a9fb310f
31-10-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/16123 Date: 2023-10-10 15:09:41 +0000
10-10-2023

Pure parsing of the classfile by ClassFile API was too weak validation, because lazy-initialized class elements did not reveal even obvious problems. Verification seems to be much more complex validation of the class, however it includes also assignability checks of the referenced types. Default class hierarchy resolver seems to miss access to some of the referenced classes. One possible fix would be to provide class hierarchy resolver with full access, however that seems to be too complex for the desired goal. I propose a fix mocking class hierarchy resolver so it effectively skips assignability validation. Alternatively it can be fixed by replacement of the full class verification with deep class model traversal only (as the original code did before conversion to ClassFile API).
07-10-2023