The JVM considers classes loaded by the bootloader to be trusted and will skip bytecode verification. The crash comes from a random location in ClassFileParser.cpp.
Add the flag -Xverify:all and the flag "BytecodeVerificationLocal" will be set, turning on the verification of classes loaded by the bootloader.
The problem comes from the malformed class:
"jdk/internal/module/SystemModuleFinders$1$$Lambda"
parse_interfaces() reads the length of 1 interface, described at offset 483.
The class index for this interface is then read from offset 485; it is 0x1a (0n26).
However, the value (type) at this index (0n26) is not a JVM_CONSTANT_Class, but JVM_CONSTANT_UTF8, representing the string "java/security/PrivilegedAction".
With verification turned on, a java/lang/ClassFormatError will be thrown with the
following message:
"Interface name has bad constant pool index 26 in class file jdk.internal.module.SystemModuleFinders$1$$Lambda"
Hence, with -Xverify:all you should see the following:
"Error occurred during initialization of boot layer
java.lang.InternalError: java.lang.ClassFormatError: Interface name has bad constant pool index 26 in class file jdk/internal/module/SystemModuleFinders$1$$Lambda
Caused by: java.lang.ClassFormatError: Interface name has bad constant pool index 26 in class file jdk/internal/module/SystemModuleFinders$1$$Lambda"
The crash report is an actual crash, not an assert (because it is a product build). The reason is here:
// ClassFileParser.cpp
inline void check_property(bool property,
const char* msg,
int index,
TRAPS) const {
if (_need_verify) {
guarantee_property(property, msg, index, CHECK);
} else {
assert_property(property, msg, index, CHECK);
}
}
inline void assert_property(bool b, const char* msg, int index, TRAPS) const {
#ifdef ASSERT
if (!b) {
report_assert_property_failure(msg, index, THREAD);
}
#endif
}
This construction is not complete because no action is taken for product builds. This leads to crashes later, not at the point of error discovery.
Perhaps the branch for !_need_verify in check_property() should be split: guarantee_property(), which throws ClassFormatError, for product builds, and assert_property() for non-product builds. (edited)
An argument for this is that system classes are built mainly through core-libs, and it is more valuable for them to get a ClassFormatError compared to the VM crashing or asserting.
Add the flag -Xverify:all and the flag "BytecodeVerificationLocal" will be set, turning on the verification of classes loaded by the bootloader.
The problem comes from the malformed class:
"jdk/internal/module/SystemModuleFinders$1$$Lambda"
parse_interfaces() reads the length of 1 interface, described at offset 483.
The class index for this interface is then read from offset 485; it is 0x1a (0n26).
However, the value (type) at this index (0n26) is not a JVM_CONSTANT_Class, but JVM_CONSTANT_UTF8, representing the string "java/security/PrivilegedAction".
With verification turned on, a java/lang/ClassFormatError will be thrown with the
following message:
"Interface name has bad constant pool index 26 in class file jdk.internal.module.SystemModuleFinders$1$$Lambda"
Hence, with -Xverify:all you should see the following:
"Error occurred during initialization of boot layer
java.lang.InternalError: java.lang.ClassFormatError: Interface name has bad constant pool index 26 in class file jdk/internal/module/SystemModuleFinders$1$$Lambda
Caused by: java.lang.ClassFormatError: Interface name has bad constant pool index 26 in class file jdk/internal/module/SystemModuleFinders$1$$Lambda"
The crash report is an actual crash, not an assert (because it is a product build). The reason is here:
// ClassFileParser.cpp
inline void check_property(bool property,
const char* msg,
int index,
TRAPS) const {
if (_need_verify) {
guarantee_property(property, msg, index, CHECK);
} else {
assert_property(property, msg, index, CHECK);
}
}
inline void assert_property(bool b, const char* msg, int index, TRAPS) const {
#ifdef ASSERT
if (!b) {
report_assert_property_failure(msg, index, THREAD);
}
#endif
}
This construction is not complete because no action is taken for product builds. This leads to crashes later, not at the point of error discovery.
Perhaps the branch for !_need_verify in check_property() should be split: guarantee_property(), which throws ClassFormatError, for product builds, and assert_property() for non-product builds. (edited)
An argument for this is that system classes are built mainly through core-libs, and it is more valuable for them to get a ClassFormatError compared to the VM crashing or asserting.
- links to
-
Commit(master) openjdk/jdk/28d23ada
-
Review(master) openjdk/jdk/21626