Skip to content

Commit 40f696d

Browse files
committed
8356318: Unexpected VerifyError in AOT training run
Reviewed-by: shade, kvn
1 parent da5dc52 commit 40f696d

File tree

4 files changed

+185
-10
lines changed

4 files changed

+185
-10
lines changed

src/hotspot/share/classfile/verifier.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,9 @@ bool Verifier::verify(InstanceKlass* klass, bool should_verify_class, TRAPS) {
223223
split_verifier.verify_class(THREAD);
224224
exception_name = split_verifier.result();
225225

226-
// If dumping static archive then don't fall back to the old verifier on
227-
// verification failure. If a class fails verification with the split verifier,
228-
// it might fail the CDS runtime verifier constraint check. In that case, we
229-
// don't want to share the class. We only archive classes that pass the split
230-
// verifier.
231-
bool can_failover = !CDSConfig::is_dumping_static_archive() &&
226+
// If dumping {classic, final} static archive, don't bother to run the old verifier, as
227+
// the class will be excluded from the archive anyway.
228+
bool can_failover = !(CDSConfig::is_dumping_classic_static_archive() || CDSConfig::is_dumping_final_static_archive()) &&
232229
klass->major_version() < NOFAILOVER_MAJOR_VERSION;
233230

234231
if (can_failover && !HAS_PENDING_EXCEPTION && // Split verifier doesn't set PENDING_EXCEPTION for failure
@@ -237,9 +234,10 @@ bool Verifier::verify(InstanceKlass* klass, bool should_verify_class, TRAPS) {
237234
log_info(verification)("Fail over class verification to old verifier for: %s", klass->external_name());
238235
log_info(class, init)("Fail over class verification to old verifier for: %s", klass->external_name());
239236
#if INCLUDE_CDS
240-
// Exclude any classes that fail over during dynamic dumping
241-
if (CDSConfig::is_dumping_dynamic_archive()) {
242-
SystemDictionaryShared::warn_excluded(klass, "Failed over class verification while dynamic dumping");
237+
// Exclude any classes that are verified with the old verifier, as the old verifier
238+
// doesn't call SystemDictionaryShared::add_verification_constraint()
239+
if (CDSConfig::is_dumping_archive()) {
240+
SystemDictionaryShared::warn_excluded(klass, "Verified with old verifier");
243241
SystemDictionaryShared::set_excluded(klass);
244242
}
245243
#endif
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*
23+
*/
24+
25+
/*
26+
* @test
27+
* @summary Sanity test for AOTCache
28+
* @requires vm.cds.supports.aot.class.linking
29+
* @comment work around JDK-8345635
30+
* @requires !vm.jvmci.enabled
31+
* @library /test/lib
32+
* @build VerifierFailOver_Helper
33+
* @build VerifierFailOver
34+
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar VerifierFailOverApp VerifierFailOver_Helper
35+
* @run driver VerifierFailOver
36+
*/
37+
38+
import jdk.test.lib.cds.SimpleCDSAppTester;
39+
import jdk.test.lib.process.OutputAnalyzer;
40+
41+
public class VerifierFailOver {
42+
public static void main(String... args) throws Exception {
43+
SimpleCDSAppTester.of("VerifierFailOver")
44+
.addVmArgs("-Xlog:cds+class=debug")
45+
.classpath("app.jar")
46+
.appCommandLine("VerifierFailOverApp")
47+
.setTrainingChecker((OutputAnalyzer out) -> {
48+
out.shouldContain("Skipping VerifierFailOver_Helper: Verified with old verifier");
49+
})
50+
.setAssemblyChecker((OutputAnalyzer out) -> {
51+
// classes verified with fail-over mode should not be cached.
52+
out.shouldMatch("class.* klasses.* VerifierFailOverApp");
53+
out.shouldNotMatch("class.* klasses.* VerifierFailOver_Helper");
54+
})
55+
.runAOTWorkflow();
56+
}
57+
}
58+
59+
class VerifierFailOverApp {
60+
public static void main(String[] args) throws Throwable {
61+
Class goodClass = Class.forName("VerifierFailOver_Helper");
62+
Object obj = goodClass.newInstance();
63+
System.out.println("Successfully loaded: " + obj.getClass().getName());
64+
}
65+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*
23+
*/
24+
25+
// This class should be rejected by the new verifier, but will be accepted by the old verifier.
26+
27+
class VerifierFailOver_Helper {
28+
0xCAFEBABE;
29+
0;
30+
50;
31+
[] { // Constant Pool
32+
; // first element is empty
33+
Method #3 #5; // #1
34+
Utf8 "StackMapTable"; // #2
35+
class #4; // #3
36+
Utf8 "java/lang/Object"; // #4
37+
NameAndType #12 #7; // #5
38+
Utf8 "SourceFile"; // #6
39+
Utf8 "()V"; // #7
40+
class #9; // #8
41+
Utf8 "VerifierFailOver_Helper"; // #9
42+
Utf8 "Code"; // #10
43+
Utf8 "VerifierFailOver_Helper.jasm"; // #11
44+
Utf8 "<init>"; // #12
45+
Utf8 "stackmap"; // #13
46+
} // Constant Pool
47+
48+
0x0000; // access
49+
#8;// this_cpx
50+
#3;// super_cpx
51+
52+
[] { // Interfaces
53+
} // Interfaces
54+
55+
[] { // fields
56+
} // fields
57+
58+
[] { // methods
59+
{ // Member
60+
0x0001; // access
61+
#12; // name_cpx
62+
#7; // sig_cpx
63+
[] { // Attributes
64+
Attr(#10) { // Code
65+
1; // max_stack
66+
1; // max_locals
67+
Bytes[]{
68+
0x2AB70001B100B1;
69+
};
70+
[] { // Traps
71+
} // end Traps
72+
[] { // Attributes
73+
/* right:
74+
Attr(#2) { // StackMap
75+
end right */
76+
// wrong:
77+
Attr(#13) { // stackmap
78+
// end wrong
79+
[] { //
80+
255b, 5, []{I}, []{};
81+
}
82+
} // end StackMap
83+
} // Attributes
84+
} // end Code
85+
} // Attributes
86+
} // Member
87+
} // methods
88+
89+
[] { // Attributes
90+
Attr(#6) { // SourceFile
91+
#11;
92+
} // end SourceFile
93+
} // Attributes
94+
} // end class stackmap00303m1n
95+
96+

test/lib/jdk/test/lib/cds/SimpleCDSAppTester.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
*/
5252
public class SimpleCDSAppTester {
5353
private String name;
54+
private BiConsumer<OutputAnalyzer, RunMode> trainingChecker;
5455
private BiConsumer<OutputAnalyzer, RunMode> assemblyChecker;
5556
private BiConsumer<OutputAnalyzer, RunMode> productionChecker;
5657
private String classpath;
@@ -100,6 +101,11 @@ public SimpleCDSAppTester appCommandLine(String... args) {
100101
return this;
101102
}
102103

104+
public SimpleCDSAppTester setTrainingChecker(BiConsumer<OutputAnalyzer, RunMode> checker) {
105+
this.trainingChecker = checker;
106+
return this;
107+
}
108+
103109
public SimpleCDSAppTester setAssemblyChecker(BiConsumer<OutputAnalyzer, RunMode> checker) {
104110
this.assemblyChecker = checker;
105111
return this;
@@ -110,6 +116,12 @@ public SimpleCDSAppTester setProductionChecker(BiConsumer<OutputAnalyzer, RunMod
110116
return this;
111117
}
112118

119+
public SimpleCDSAppTester setTrainingChecker(Consumer<OutputAnalyzer> checker) {
120+
this.trainingChecker = (OutputAnalyzer out, RunMode runMode) -> {
121+
checker.accept(out);
122+
};
123+
return this;
124+
}
113125

114126
public SimpleCDSAppTester setAssemblyChecker(Consumer<OutputAnalyzer> checker) {
115127
this.assemblyChecker = (OutputAnalyzer out, RunMode runMode) -> {
@@ -152,7 +164,11 @@ public String[] appCommandLine(RunMode runMode) {
152164

153165
@Override
154166
public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception {
155-
if (isDumping(runMode) && runMode != RunMode.TRAINING) {
167+
if (runMode == RunMode.TRAINING) {
168+
if (trainingChecker != null) {
169+
trainingChecker.accept(out, runMode);
170+
}
171+
} else if (isDumping(runMode)) {
156172
if (assemblyChecker != null) {
157173
assemblyChecker.accept(out, runMode);
158174
}

0 commit comments

Comments
 (0)