1 /*
2  * Copyright (C) 2017 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 package art;
18 
19 import java.util.Arrays;
20 import java.util.Objects;
21 import java.lang.reflect.Executable;
22 import java.lang.reflect.Method;
23 
24 public class Test1927 {
25   private static boolean PRINT_FULL_EXCEPTION = false;
PrintStack()26   private static void PrintStack() {
27     System.out.println("\tCurrent Stack:");
28     for (StackTrace.StackFrameData e : StackTrace.GetStackTrace(Thread.currentThread())) {
29       if (Objects.equals(e.method.getDeclaringClass().getPackage(), Test1927.class.getPackage())) {
30         System.out.println("\t\t" + e.method + " @ line = " +
31             Breakpoint.locationToLine(e.method, e.current_location));
32       }
33     }
34   }
35 
ExceptionCatchEvent(Thread thr, Executable catch_method, long catch_location, Throwable exception)36   public static void ExceptionCatchEvent(Thread thr,
37                                          Executable catch_method,
38                                          long catch_location,
39                                          Throwable exception) {
40     System.out.println(thr.getName() + ": " + catch_method + " @ line = " +
41         Breakpoint.locationToLine(catch_method, catch_location) + " caught " +
42         exception.getClass() + ": " + exception.getMessage());
43     PrintStack();
44     if (PRINT_FULL_EXCEPTION) {
45       System.out.print("exception is: ");
46       exception.printStackTrace(System.out);
47     }
48   }
49 
ExceptionEvent(Thread thr, Executable throw_method, long throw_location, Throwable exception, Executable catch_method, long catch_location)50   public static void ExceptionEvent(Thread thr,
51                                     Executable throw_method,
52                                     long throw_location,
53                                     Throwable exception,
54                                     Executable catch_method,
55                                     long catch_location) {
56     System.out.println(thr.getName() + ": " + throw_method + " @ line = " +
57         Breakpoint.locationToLine(throw_method, throw_location) + " throws " +
58         exception.getClass() + ": " + exception.getMessage());
59     String catch_message;
60     if (catch_method == null) {
61       catch_message = "<UNKNOWN>";
62     } else {
63       catch_message = catch_method.toString() + " @ line = " +
64           Breakpoint.locationToLine(catch_method, catch_location);
65     }
66     PrintStack();
67     System.out.println("\tWill be caught by: " + catch_message);
68     if (PRINT_FULL_EXCEPTION) {
69       System.out.print("exception is: ");
70       exception.printStackTrace(System.out);
71     }
72   }
73 
74   public static class TestException extends Error {
TestException(String s)75     public TestException(String s) { super(s); }
TestException()76     public TestException() { super("from java"); }
77   }
78 
79   // Possibilities
80   // ( -> is a JNI/Java call.)
81   // Furthest left catches/clears the exception
82   // Furthest right throws it.
83   // J
84   // N
85   // J -> J
86   // J -> N
87   // N -> J
88   // N -> N
89   // J -> J -> J
90   // J -> J -> N
91   // J -> N -> J
92   // J -> N -> N
93   // N -> J -> J
94   // N -> J -> N
95   // N -> N -> J
96   // N -> N -> N
97   // extra -> N -> J -> J
98   // extra -> N -> J -> N
99   // extra -> N -> N -> J
100   // extra -> N -> N -> N
101 
terminal_J()102   public static void terminal_J() {
103     throw new TestException();
104   }
105 
terminal_N()106   public static native void terminal_N();
107 
test_J()108   public static void test_J() {
109     try {
110       throw new TestException();
111     } catch (TestException e) {
112       printException(e);
113     }
114   }
115 
116   // Do test_J but native
test_N()117   public static native void test_N();
118 
test_J_J()119   public static void test_J_J() {
120     try {
121       terminal_J();
122     } catch (TestException e) {
123       printException(e);
124     }
125   }
126 
test_J_N()127   public static void test_J_N() {
128     try {
129       terminal_N();
130     } catch (TestException e) {
131       printException(e);
132     }
133   }
134 
test_N_J()135   public static native void test_N_J();
test_N_N()136   public static native void test_N_N();
137 
intermediate_J_J()138   public static void intermediate_J_J() { terminal_J(); }
intermediate_J_N()139   public static void intermediate_J_N() { terminal_N(); }
intermediate_N_J()140   public static native void intermediate_N_J();
intermediate_N_N()141   public static native void intermediate_N_N();
142 
test_J_J_J()143   public static void test_J_J_J() {
144     try {
145       intermediate_J_J();
146     } catch (TestException e) {
147       printException(e);
148     }
149   }
150 
test_J_J_N()151   public static void test_J_J_N() {
152     try {
153       intermediate_J_N();
154     } catch (TestException e) {
155       printException(e);
156     }
157   }
158 
test_J_N_J()159   public static void test_J_N_J() {
160     try {
161       intermediate_N_J();
162     } catch (TestException e) {
163       printException(e);
164     }
165   }
166 
test_J_N_N()167   public static void test_J_N_N() {
168     try {
169       intermediate_N_N();
170     } catch (TestException e) {
171       printException(e);
172     }
173   }
174 
test_N_J_J()175   public static native void test_N_J_J();
test_N_J_N()176   public static native void test_N_J_N();
test_N_N_J()177   public static native void test_N_N_J();
test_N_N_N()178   public static native void test_N_N_N();
179 
test_extra_N_J_J()180   public static void test_extra_N_J_J() {
181     try {
182       test_N_J_J();
183     } catch (TestException e) {
184       printException(e);
185     }
186   }
test_extra_N_J_N()187   public static void test_extra_N_J_N() {
188     try {
189       test_N_J_N();
190     } catch (TestException e) {
191       printException(e);
192     }
193   }
test_extra_N_N_J()194   public static void test_extra_N_N_J() {
195     try {
196       test_N_N_J();
197     } catch (TestException e) {
198       printException(e);
199     }
200   }
test_extra_N_N_N()201   public static void test_extra_N_N_N() {
202     try {
203       test_N_N_N();
204     } catch (TestException e) {
205       printException(e);
206     }
207   }
208 
printException(Throwable e)209   public static void printException(Throwable e) {
210     System.out.println("Caught exception: " + e);
211     if (PRINT_FULL_EXCEPTION) {
212       e.printStackTrace(System.out);
213     }
214   }
215 
run()216   public static void run() throws Exception {
217     // Make sure classes are loaded first.
218     System.out.println(TestException.class.toString());
219     Exceptions.setupExceptionTracing(
220         Test1927.class,
221         TestException.class,
222         Test1927.class.getDeclaredMethod(
223             "ExceptionEvent",
224             Thread.class,
225             Executable.class,
226             Long.TYPE,
227             Throwable.class,
228             Executable.class,
229             Long.TYPE),
230         Test1927.class.getDeclaredMethod(
231             "ExceptionCatchEvent",
232             Thread.class,
233             Executable.class,
234             Long.TYPE,
235             Throwable.class));
236     Exceptions.enableExceptionEvent(Thread.currentThread());
237     Exceptions.enableExceptionCatchEvent(Thread.currentThread());
238     System.out.println("Running test_J");
239     test_J();
240     System.out.println("Running test_N()");
241     test_N();
242     System.out.println("Running test_J_J()");
243     test_J_J();
244     System.out.println("Running test_J_N()");
245     test_J_N();
246     System.out.println("Running test_N_J()");
247     test_N_J();
248     System.out.println("Running test_N_N()");
249     test_N_N();
250     System.out.println("Running test_J_J_J()");
251     test_J_J_J();
252     System.out.println("Running test_J_J_N()");
253     test_J_J_N();
254     System.out.println("Running test_J_N_J()");
255     test_J_N_J();
256     System.out.println("Running test_J_N_N()");
257     test_J_N_N();
258     System.out.println("Running test_N_J_J()");
259     test_N_J_J();
260     System.out.println("Running test_N_J_N()");
261     test_N_J_N();
262     System.out.println("Running test_N_N_J()");
263     test_N_N_J();
264     System.out.println("Running test_N_N_N()");
265     test_N_N_N();
266     System.out.println("Running test_extra_N_J_J()");
267     test_extra_N_J_J();
268     System.out.println("Running test_extra_N_J_N()");
269     test_extra_N_J_N();
270     System.out.println("Running test_extra_N_N_J()");
271     test_extra_N_N_J();
272     System.out.println("Running test_extra_N_N_N()");
273     test_extra_N_N_N();
274     Exceptions.disableExceptionCatchEvent(Thread.currentThread());
275     Exceptions.disableExceptionEvent(Thread.currentThread());
276   }
277 }
278