xref: /aosp_15_r20/art/test/855-native/src-art/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2024 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import java.io.File;
18*795d594fSAndroid Build Coastguard Worker import java.io.IOException;
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker import dalvik.system.VMDebug;
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker public class Main {
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker     private static final String TEMP_FILE_NAME_PREFIX = "test";
25*795d594fSAndroid Build Coastguard Worker     private static final String TEMP_FILE_NAME_SUFFIX = ".trace";
26*795d594fSAndroid Build Coastguard Worker 
createTempFile()27*795d594fSAndroid Build Coastguard Worker     private static File createTempFile() throws Exception {
28*795d594fSAndroid Build Coastguard Worker         try {
29*795d594fSAndroid Build Coastguard Worker             return  File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
30*795d594fSAndroid Build Coastguard Worker         } catch (IOException e) {
31*795d594fSAndroid Build Coastguard Worker             System.setProperty("java.io.tmpdir", "/data/local/tmp");
32*795d594fSAndroid Build Coastguard Worker             try {
33*795d594fSAndroid Build Coastguard Worker                 return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
34*795d594fSAndroid Build Coastguard Worker             } catch (IOException e2) {
35*795d594fSAndroid Build Coastguard Worker                 System.setProperty("java.io.tmpdir", "/sdcard");
36*795d594fSAndroid Build Coastguard Worker                 return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
37*795d594fSAndroid Build Coastguard Worker             }
38*795d594fSAndroid Build Coastguard Worker         }
39*795d594fSAndroid Build Coastguard Worker     }
40*795d594fSAndroid Build Coastguard Worker 
main(String[] args)41*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) throws Exception {
42*795d594fSAndroid Build Coastguard Worker     System.loadLibrary(args[0]);
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker     // In case we already run in tracing mode, disable it.
45*795d594fSAndroid Build Coastguard Worker     if (VMDebug.getMethodTracingMode() != 0) {
46*795d594fSAndroid Build Coastguard Worker         VMDebug.stopMethodTracing();
47*795d594fSAndroid Build Coastguard Worker     }
48*795d594fSAndroid Build Coastguard Worker 
49*795d594fSAndroid Build Coastguard Worker     File tempFile = createTempFile();
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker     // Start method tracing so that native methods get the generic JNI stub.
52*795d594fSAndroid Build Coastguard Worker     VMDebug.startMethodTracing(tempFile.getPath(), 0, 0, false, 0);
53*795d594fSAndroid Build Coastguard Worker 
54*795d594fSAndroid Build Coastguard Worker     // We need the caller of `throwsException` to be nterp or compiled, because the clinit check is
55*795d594fSAndroid Build Coastguard Worker     // executed within the generic JNI stub. The switch interpreter does a clinit check before the
56*795d594fSAndroid Build Coastguard Worker     // invoke, and that doesn't trigger the bug.
57*795d594fSAndroid Build Coastguard Worker     Main.ensureJitCompiled(Runner.class, "run");
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker     // We want the `Test` class to be loaded after `startMethodTracing`. So we call it through
60*795d594fSAndroid Build Coastguard Worker     // `Runner` to avoid the verification of the `Main` class preload `Test`.
61*795d594fSAndroid Build Coastguard Worker     Runner.run();
62*795d594fSAndroid Build Coastguard Worker   }
63*795d594fSAndroid Build Coastguard Worker 
ensureJitCompiled(Class<?> cls, String method)64*795d594fSAndroid Build Coastguard Worker   public static native void ensureJitCompiled(Class<?> cls, String method);
65*795d594fSAndroid Build Coastguard Worker }
66*795d594fSAndroid Build Coastguard Worker 
67*795d594fSAndroid Build Coastguard Worker class Runner {
run()68*795d594fSAndroid Build Coastguard Worker   public static void run() {
69*795d594fSAndroid Build Coastguard Worker     try {
70*795d594fSAndroid Build Coastguard Worker         // Will call through the generic JNI stub and when returning from the native code will need
71*795d594fSAndroid Build Coastguard Worker         // to walk the stack to throw the exception. We used to crash when walking the stack because
72*795d594fSAndroid Build Coastguard Worker         // we did not expect to have a generic JNI PC with an entrypoint from a shared boot image
73*795d594fSAndroid Build Coastguard Worker         // JNI stub.
74*795d594fSAndroid Build Coastguard Worker         Test.throwsException();
75*795d594fSAndroid Build Coastguard Worker     } catch (Test e) {
76*795d594fSAndroid Build Coastguard Worker         if (!Test.ranInitializer) {
77*795d594fSAndroid Build Coastguard Worker             throw new Error("Expected Test.ranInitializer to be true");
78*795d594fSAndroid Build Coastguard Worker         }
79*795d594fSAndroid Build Coastguard Worker         return;
80*795d594fSAndroid Build Coastguard Worker     }
81*795d594fSAndroid Build Coastguard Worker     throw new Error("Expected exception");
82*795d594fSAndroid Build Coastguard Worker   }
83*795d594fSAndroid Build Coastguard Worker }
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker class Test extends Exception {
86*795d594fSAndroid Build Coastguard Worker   static {
87*795d594fSAndroid Build Coastguard Worker       ranInitializer = true;
88*795d594fSAndroid Build Coastguard Worker       // Will update the entrypoint of `Test.throwsException` to point to a JNI stub from the boot
89*795d594fSAndroid Build Coastguard Worker       // image.
VMDebug.stopMethodTracing()90*795d594fSAndroid Build Coastguard Worker       VMDebug.stopMethodTracing();
91*795d594fSAndroid Build Coastguard Worker   }
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker   static boolean ranInitializer;
throwsException()94*795d594fSAndroid Build Coastguard Worker   static native void throwsException() throws Test;
95*795d594fSAndroid Build Coastguard Worker }
96