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 id=aot
27 * @requires vm.cds.supports.aot.class.linking
28 * @comment work around JDK-8345635
29 * @requires !vm.jvmci.enabled
30 * @library /test/jdk/lib/testlibrary /test/lib
31 * @build EndTrainingOnMethodEntry
32 * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar MyTestApp ShouldBeCached ShouldNotBeCached
33 * @run driver EndTrainingOnMethodEntry AOT
34 */
35
36 import jdk.test.lib.cds.CDSAppTester;
37 import jdk.test.lib.helpers.ClassFileInstaller;
38 import jdk.test.lib.process.OutputAnalyzer;
39
40 public class EndTrainingOnMethodEntry {
41 static final String appJar = ClassFileInstaller.getJarPath("app.jar");
42 static final String mainClass = "MyTestApp";
43
44 public static void main(String[] args) throws Exception {
45 // We want to test the entry count implementation in both interpreter and compiler.
46 (new Tester(1)).run(args);
47 (new Tester(10)).run(args); // the loop will probably be interpreted
48 (new Tester(10000)).run(args); // the loop will probably be compiled.
49 }
50
51 static class Tester extends CDSAppTester {
52 int count;
53
54 public Tester(int count) {
55 super(mainClass);
56 this.count = count;
57 }
58
59 @Override
60 public String classpath(RunMode runMode) {
61 return appJar;
62 }
63
64 public String[] vmArgs(RunMode runMode) {
65 String stop = count > 1 ? ("stopTrainingOnMeWithCount,count=" + count) : "stopTrainingOnMe";
66 return new String[] {
67 "-Xlog:aot+class=debug",
68 "-Xlog:cds+class=debug",
69 "-XX:AOTEndTrainingOnMethodEntry=MyTestApp." + stop,
70 };
71 }
72
73 @Override
74 public String[] appCommandLine(RunMode runMode) {
75 return new String[] {
76 mainClass, runMode.name(), Integer.toString(count),
77 };
78 }
79
80 @Override
81 public void checkExecution(OutputAnalyzer out, RunMode runMode) {
82 if (runMode.isApplicationExecuted()) {
83 out.shouldContain("Hello Leyden " + runMode.name());
84 out.shouldContain("ShouldBeCached.dummy()");
85 out.shouldContain("ShouldNotBeCached.dummy()");
86 }
87 if (isDumping(runMode)) {
88 if (isAOTWorkflow()) {
89 out.shouldMatch("aot,class.* ShouldBeCached");
90 out.shouldNotMatch("aot,class.* ShouldNotBeCached");
91 } else {
92 out.shouldMatch("cds,class.* ShouldBeCached");
93 out.shouldNotMatch("cds,class.* ShouldNotBeCached");
94 }
95 }
96 }
97 }
98 }
99
100 class MyTestApp {
101 public static int COUNT;
102 public static void main(String args[]) throws Exception {
103 System.out.println("Hello Leyden " + args[0] + ", count = " + args[1]);
104 COUNT = Integer.parseInt(args[1]);
105 if (COUNT > 1) {
106 int max = COUNT + 10;
107 for (int i = 0; i < max; i++) {
108 stopTrainingOnMeWithCount(i);
109 }
110 } else {
111 ShouldBeCached.dummy();
112 stopTrainingOnMe();
113 }
114 }
115
116 static void stopTrainingOnMe() {
117 // The AOT configuration file should have been recorded before the body
118 // of this method is executed, so the ShouldNotBeCached class should not be
119 // recorded in the config.
120 ShouldNotBeCached.dummy();
121 }
122
123 static void stopTrainingOnMeWithCount(int i) {
124 if (i >= COUNT - 2) {
125 ShouldBeCached.dummy();
126 }
127 if (i >= COUNT) {
128 // The AOT configuration file should have been recorded before this block is entered,
129 // so the ShouldNotBeCached class should not be recorded in the config.
130 ShouldNotBeCached.dummy();
131 }
132 }
133 }
134
135 class ShouldBeCached {
136 static void dummy() {
137 System.out.println("ShouldBeCached.dummy()");
138 }
139 }
140
141 class ShouldNotBeCached {
142 static void dummy() {
143 System.out.println("ShouldNotBeCached.dummy()");
144 }
145 }