xref: /aosp_15_r20/art/test/2246-trace-v2/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import java.io.File;
18 import java.io.FileDescriptor;
19 import java.io.FileOutputStream;
20 import java.io.IOException;
21 import java.lang.reflect.Method;
22 
23 public class Main {
24     private static final String TEMP_FILE_NAME_PREFIX = "test";
25     private static final String TEMP_FILE_NAME_SUFFIX = ".trace";
26     private static final int WALL_CLOCK_FLAG = 0x010;
27     private static final int TRACE_OUTPUT_V2_FLAG = 0b010;
28     private static final int STREAMING_DUAL_CLOCK_VERSION = 1;
29     private static final int STREAMING_WALL_CLOCK_VERSION = 1;
30     private static File file;
31 
main(String[] args)32     public static void main(String[] args) throws Exception {
33         System.loadLibrary(args[0]);
34         String name = System.getProperty("java.vm.name");
35         if (!"Dalvik".equals(name)) {
36             System.out.println("This test is not supported on " + name);
37             return;
38         }
39 
40         ensureJitCompiled(Main.class, "$noinline$doSomeWorkJIT");
41 
42         System.out.println("***** streaming test - dual clock *******");
43         testTracing(/* streaming=*/true, /* flags= */ 0);
44 
45         System.out.println("***** streaming test - wall clock *******");
46         testTracing(/* streaming=*/true, /* flags= */ WALL_CLOCK_FLAG);
47 
48         System.out.println("***** non-streaming test - dual clock *******");
49         testTracing(/* streaming=*/false, /* flags= */ 0);
50 
51         System.out.println("***** non-streaming test - wall clock *******");
52         testTracing(/* streaming=*/false, /* flags= */ WALL_CLOCK_FLAG);
53     }
54 
testTracing(boolean streaming, int flags)55     public static void testTracing(boolean streaming, int flags) throws Exception {
56         Main m = new Main();
57         Thread t = new Thread(() -> {
58             try {
59                 file = createTempFile();
60                 FileOutputStream out_file = new FileOutputStream(file);
61                 VMDebug.startMethodTracingV2(
62                         file.getPath(), out_file.getFD(), 0, flags, false, 0, streaming);
63                 Main m1 = new Main();
64                 m1.$noinline$doSomeWork();
65                 // Call JITed code multiple times to flush out any issues with timestamps.
66                 for (int i = 0; i < 20; i++) {
67                     m.$noinline$doSomeWorkJIT();
68                 }
69                 VMDebug.$noinline$stopMethodTracing();
70                 out_file.close();
71                 dumpTrace(file.getAbsolutePath(), "TestThread2246");
72                 file.delete();
73             } catch (Exception e) {
74                 System.out.println("Exception in thread " + e);
75                 e.printStackTrace();
76             } finally {
77                 file.delete();
78             }
79         }, "TestThread2246");
80         try {
81             if (VMDebug.getMethodTracingMode() != 0) {
82                 VMDebug.$noinline$stopMethodTracing();
83             }
84 
85             t.start();
86             t.join();
87 
88             file = createTempFile();
89             FileOutputStream main_out_file = new FileOutputStream(file);
90             VMDebug.startMethodTracingV2(
91                     file.getPath(), main_out_file.getFD(), 0, flags, false, 0, streaming);
92             m.$noinline$doSomeWork();
93             // Call JITed code multiple times to flush out any issues with timestamps.
94             for (int i = 0; i < 20; i++) {
95                 m.$noinline$doSomeWorkJIT();
96             }
97             m.doSomeWorkThrow();
98             VMDebug.$noinline$stopMethodTracing();
99             main_out_file.close();
100             dumpTrace(file.getAbsolutePath(), "main");
101             file.delete();
102         } finally {
103             file.delete();
104         }
105     }
106 
createTempFile()107     private static File createTempFile() throws Exception {
108         try {
109             return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
110         } catch (IOException e) {
111             System.setProperty("java.io.tmpdir", "/data/local/tmp");
112             try {
113                 return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
114             } catch (IOException e2) {
115                 System.setProperty("java.io.tmpdir", "/sdcard");
116                 return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
117             }
118         }
119     }
120 
callOuterFunction()121     public void callOuterFunction() {
122         callLeafFunction();
123     }
124 
callLeafFunction()125     public void callLeafFunction() {}
126 
$noinline$doSomeWork()127     public void $noinline$doSomeWork() {
128         callOuterFunction();
129         callLeafFunction();
130     }
131 
$noinline$doSomeWorkJIT()132     public void $noinline$doSomeWorkJIT() {
133         callOuterFunction();
134         callLeafFunction();
135     }
136 
callThrowFunction()137     public void callThrowFunction() throws Exception {
138         throw new Exception("test");
139     }
140 
doSomeWorkThrow()141     public void doSomeWorkThrow() {
142         try {
143             callThrowFunction();
144         } catch (Exception e) {
145         }
146     }
147 
148     private static class VMDebug {
149         private static final Method startMethodTracingMethod;
150         private static final Method stopMethodTracingMethod;
151         private static final Method getMethodTracingModeMethod;
152         static {
153             try {
154                 Class<?> c = Class.forName("dalvik.system.VMDebug");
155                 startMethodTracingMethod = c.getDeclaredMethod("startMethodTracing", String.class,
156                         FileDescriptor.class, Integer.TYPE, Integer.TYPE, Boolean.TYPE,
157                         Integer.TYPE, Boolean.TYPE);
158                 stopMethodTracingMethod = c.getDeclaredMethod("stopMethodTracing");
159                 getMethodTracingModeMethod = c.getDeclaredMethod("getMethodTracingMode");
160             } catch (Exception e) {
161                 throw new RuntimeException(e);
162             }
163         }
164 
startMethodTracingV2(String filename, FileDescriptor fd, int bufferSize, int flags, boolean samplingEnabled, int intervalUs, boolean streaming)165         public static void startMethodTracingV2(String filename, FileDescriptor fd, int bufferSize,
166                 int flags, boolean samplingEnabled, int intervalUs, boolean streaming)
167                 throws Exception {
168             startMethodTracingMethod.invoke(null, filename, fd, bufferSize,
169                     flags | TRACE_OUTPUT_V2_FLAG, samplingEnabled, intervalUs, streaming);
170         }
$noinline$stopMethodTracing()171         public static void $noinline$stopMethodTracing() throws Exception {
172             stopMethodTracingMethod.invoke(null);
173         }
getMethodTracingMode()174         public static int getMethodTracingMode() throws Exception {
175             return (int) getMethodTracingModeMethod.invoke(null);
176         }
177     }
178 
ensureJitCompiled(Class<?> cls, String methodName)179     private static native void ensureJitCompiled(Class<?> cls, String methodName);
dumpTrace(String fileName, String threadName)180     private static native void dumpTrace(String fileName, String threadName);
181 }
182