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  * @modules java.management
 32  * @build EndTrainingWithAOTCacheMXBean
 33  * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar MyTestApp ShouldBeCached ShouldNotBeCached
 34  * @run driver EndTrainingWithAOTCacheMXBean AOT
 35  */
 36 
 37 import jdk.test.lib.cds.CDSAppTester;
 38 import jdk.test.lib.helpers.ClassFileInstaller;
 39 import jdk.test.lib.process.OutputAnalyzer;
 40 import java.lang.management.ManagementFactory;
 41 import jdk.management.AOTCacheMXBean;
 42 
 43 public class EndTrainingWithAOTCacheMXBean {
 44     static final String appJar = ClassFileInstaller.getJarPath("app.jar");
 45     static final String mainClass = "MyTestApp";
 46 
 47     public static void main(String[] args) throws Exception {
 48         // We want to test the entry count implementation in both interpreter and compiler.
 49         new Tester().run(args);
 50     }
 51 
 52     static class Tester extends CDSAppTester {
 53 
 54         public Tester() {
 55             super(mainClass);
 56         }
 57 
 58         @Override
 59         public String classpath(RunMode runMode) {
 60             return appJar;
 61         }
 62 
 63         public String[] vmArgs(RunMode runMode) {
 64             return new String[] {
 65                 "-Xlog:cds+class=debug",
 66                 "-Xlog:aot+class=debug",
 67                 "--add-modules=jdk.management"
 68             };
 69         }
 70 
 71         @Override
 72         public String[] appCommandLine(RunMode runMode) {
 73             return new String[] {
 74                 mainClass, runMode.name(),
 75             };
 76         }
 77 
 78         @Override
 79         public void checkExecution(OutputAnalyzer out, RunMode runMode) {
 80             var name = runMode.name();
 81             if (runMode.isApplicationExecuted()) {
 82                 out.shouldContain("Hello Leyden " + name);
 83                 out.shouldContain("ShouldBeCached.dummy()");
 84                 out.shouldContain("ShouldNotBeCached.dummy()");
 85                 if(runMode == RunMode.TRAINING) {
 86                     out.shouldContain("AOTMode = record");
 87                     out.shouldContain("Confirmed is recording");
 88                     out.shouldContain("Confirmed recording duration > 0");
 89                     out.shouldContain("Stopped recording successfully after an additional 10ms");
 90                     out.shouldContain("Last recording duration > than previous duration");
 91                     out.shouldContain("Confirmed recording stopped");
 92                     out.shouldContain("Confirmed recording duration has not changed after 10ms");
 93                 } else if (runMode == RunMode.ASSEMBLY) {
 94                     out.shouldNotContain("Hello Leyden ");
 95                 } else if (runMode == RunMode.PRODUCTION) {
 96                     out.shouldContain("AOTMode = on");
 97                     out.shouldContain("Confirmed is not recording");
 98                     out.shouldContain("Confirmed recording duration == 0");
 99                 }
100                 out.shouldNotContain("Thread interrupted");
101                 out.shouldNotContain("Failed to stop recording");
102             }
103             if (isDumping(runMode)) {
104                 if (isAOTWorkflow()) {
105                     out.shouldMatch("aot,class.* ShouldBeCached");
106                     out.shouldNotMatch("aot,class.* ShouldNotBeCached");
107                 } else {
108                     out.shouldMatch("cds,class.* ShouldBeCached");
109                     out.shouldNotMatch("cds,class.* ShouldNotBeCached");
110                 }
111             }
112         }
113     }
114 }
115 
116 class MyTestApp {
117     public static void main(String args[]) throws Exception {
118         System.out.println("Hello Leyden " + args[0]);
119         var aotBean = ManagementFactory.getPlatformMXBean(AOTCacheMXBean.class);
120         if (aotBean == null) {
121             System.out.println("AOTCacheMXBean is not available");
122             return;
123         }
124         ShouldBeCached.dummy();
125         System.out.println("AOTMode = " + aotBean.getMode());
126         if (aotBean.isRecording()) {
127             try {
128                 System.out.println("Confirmed is recording");
129                 var initialDuration = aotBean.getRecordingDuration();
130                 System.out.println("Confirmed recording duration > 0");
131                 Thread.sleep(10);
132                 if (aotBean.endRecording()) {
133                     System.out.println("Stopped recording successfully after an additional 10ms");
134                     if (!aotBean.isRecording()) {
135                         System.out.println("Confirmed recording stopped");
136                     }
137                     var recordingDuration = aotBean.getRecordingDuration();
138                     if (recordingDuration > initialDuration) {
139                         System.out.println("Last recording duration > than previous duration");
140                     }
141                     Thread.sleep(10);
142                     var lastDuration = aotBean.getRecordingDuration();
143                     if (lastDuration == recordingDuration) {
144                         System.out.println("Confirmed recording duration has not changed after 10ms");
145                     }
146                 } else {
147                     System.out.println("Failed to stop recording");
148                 }
149             } catch (InterruptedException e) {
150                 System.out.println("Thread interrupted");
151             }
152         } else {
153             System.out.println("Confirmed is not recording");
154             var recordingDuration = aotBean.getRecordingDuration();
155             if (recordingDuration == 0) {
156                 System.out.println("Confirmed recording duration == 0");
157             }
158         }
159         ShouldNotBeCached.dummy();
160     }
161 }
162 
163 class ShouldBeCached {
164     static void dummy() {
165         System.out.println("ShouldBeCached.dummy()");
166     }
167 }
168 
169 class ShouldNotBeCached {
170     static void dummy() {
171         System.out.println("ShouldNotBeCached.dummy()");
172     }
173 }