1 /*
2  * Copyright (C) 2007 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 // An error class.
18 class BadError extends Error {
BadError(String s)19     public BadError(String s) {
20         super("This is bad by convention: " + s);
21     }
22 }
23 
24 // A class that throws BadError during static initialization.
25 class BadInit {
26     static int dummy;
27     static {
28         System.out.println("Static Init");
29         if (true) {
30             throw new BadError("BadInit");
31         }
32     }
33 }
34 
35 // An error that doesn't have a <init>(String) method.
36 class BadErrorNoStringInit extends Error {
BadErrorNoStringInit()37     public BadErrorNoStringInit() {
38         super("This is bad by convention");
39     }
40 }
41 
42 // A class that throws BadErrorNoStringInit during static initialization.
43 class BadInitNoStringInit {
44     static int dummy;
45     static {
46         System.out.println("Static BadInitNoStringInit");
47         if (true) {
BadErrorNoStringInit()48             throw new BadErrorNoStringInit();
49         }
50     }
51 }
52 
53 // A class that throws BadError during static initialization, serving as a super class.
54 class BadSuperClass {
55  static int dummy;
56  static {
57      System.out.println("BadSuperClass Static Init");
58      if (true) {
59          throw new BadError("BadInit");
60      }
61  }
62 }
63 
64 // A class that derives from BadSuperClass.
65 class DerivedFromBadSuperClass extends BadSuperClass {
66 }
67 
68 /**
69  * Exceptions across method calls
70  */
71 public class Main {
exceptions_007()72     public static void exceptions_007() {
73         try {
74             catchAndRethrow();
75         } catch (NullPointerException npe) {
76             System.out.print("Got an NPE: ");
77             System.out.println(npe.getMessage());
78             npe.printStackTrace(System.out);
79         }
80     }
main(String args[])81     public static void main(String args[]) {
82         exceptions_007();
83         exceptionsRethrowClassInitFailure();
84         exceptionsRethrowClassInitFailureNoStringInit();
85         exceptionsForSuperClassInitFailure();
86         exceptionsInMultiDex();
87     }
88 
catchAndRethrow()89     private static void catchAndRethrow() {
90         try {
91             throwNullPointerException();
92         } catch (NullPointerException npe) {
93             NullPointerException npe2;
94             npe2 = new NullPointerException("second throw");
95             npe2.initCause(npe);
96             throw npe2;
97         }
98     }
99 
throwNullPointerException()100     private static void throwNullPointerException() {
101         throw new NullPointerException("first throw");
102     }
103 
exceptionsRethrowClassInitFailure()104     private static void exceptionsRethrowClassInitFailure() {
105         try {
106             try {
107                 BadInit.dummy = 1;
108                 throw new IllegalStateException("Should not reach here.");
109             } catch (BadError e) {
110                 System.out.println(e);
111             }
112 
113             // Check if it works a second time.
114 
115             try {
116                 BadInit.dummy = 1;
117                 throw new IllegalStateException("Should not reach here.");
118             } catch (NoClassDefFoundError e) {
119                 System.out.println(e);
120                 System.out.println(e.getCause());
121             }
122         } catch (Exception error) {
123             error.printStackTrace(System.out);
124         }
125     }
126 
exceptionsRethrowClassInitFailureNoStringInit()127     private static void exceptionsRethrowClassInitFailureNoStringInit() {
128         try {
129             try {
130                 BadInitNoStringInit.dummy = 1;
131                 throw new IllegalStateException("Should not reach here.");
132             } catch (BadErrorNoStringInit e) {
133                 System.out.println(e);
134             }
135 
136             // Check if it works a second time.
137 
138             try {
139                 BadInitNoStringInit.dummy = 1;
140                 throw new IllegalStateException("Should not reach here.");
141             } catch (NoClassDefFoundError e) {
142                 System.out.println(e);
143                 System.out.println(e.getCause());
144             }
145         } catch (Exception error) {
146             error.printStackTrace(System.out);
147         }
148     }
149 
exceptionsForSuperClassInitFailure()150     private static void exceptionsForSuperClassInitFailure() {
151         try {
152             // Resolve DerivedFromBadSuperClass.
153             BadSuperClass.dummy = 1;
154             throw new IllegalStateException("Should not reach here.");
155         } catch (BadError e) {
156             System.out.println(e);
157         } catch (Throwable t) {
158             t.printStackTrace(System.out);
159         }
160         try {
161             // Before splitting ClassStatus::kError into
162             // ClassStatus::kErrorUnresolved and ClassStatus::kErrorResolved,
163             // this would trigger a
164             //     CHECK(super_class->IsResolved())
165             // failure in
166             //     ClassLinker::LoadSuperAndInterfaces().
167             // After the change we're getting either VerifyError
168             // (for Optimizing) or NoClassDefFoundError wrapping
169             // BadError (for interpreter or JIT).
170             new DerivedFromBadSuperClass();
171             throw new IllegalStateException("Should not reach here.");
172         } catch (NoClassDefFoundError ncdfe) {
173             if (!(ncdfe.getCause() instanceof BadError)) {
174                 ncdfe.getCause().printStackTrace(System.out);
175             }
176         } catch (VerifyError e) {
177         } catch (Throwable t) {
178             t.printStackTrace(System.out);
179         }
180     }
181 
exceptionsInMultiDex()182     private static void exceptionsInMultiDex() {
183         try {
184             MultiDexBadInit.dummy = 1;
185             throw new IllegalStateException("Should not reach here.");
186         } catch (Error e) {
187             System.out.println(e);
188         } catch (Throwable t) {
189             t.printStackTrace(System.out);
190         }
191         // Before splitting ClassStatus::kError into
192         // ClassStatus::kErrorUnresolved and ClassStatus::kErrorResolved,
193         // the exception from wrapper 1 would have been
194         // wrapped in NoClassDefFoundError but the exception
195         // from wrapper 2 would have been unwrapped.
196         try {
197             MultiDexBadInitWrapper1.setDummy(1);
198             throw new IllegalStateException("Should not reach here.");
199         } catch (NoClassDefFoundError ncdfe) {
200             System.out.println(ncdfe);
201             System.out.println("  cause: " + ncdfe.getCause());
202         } catch (Throwable t) {
203             t.printStackTrace(System.out);
204         }
205         try {
206             MultiDexBadInitWrapper2.setDummy(1);
207             throw new IllegalStateException("Should not reach here.");
208         } catch (NoClassDefFoundError ncdfe) {
209             System.out.println(ncdfe);
210             System.out.println("  cause: " + ncdfe.getCause());
211         } catch (Throwable t) {
212             t.printStackTrace(System.out);
213         }
214     }
215 }
216