1 /*
2  * Copyright (C) 2010 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 public class Main {
18     static {
staticMethodCalledByClinit()19         staticMethodCalledByClinit();
20     }
21 
staticMethodCalledByClinit()22     private static void staticMethodCalledByClinit() {
23         // Test that DeliverException works when we need to unwind to a handler -- this method --
24         // that is currently a resolution stub because it's running on behalf of <clinit>.
25         try {
26             throwDuringClinit();
27             System.err.println("didn't throw!");
28         } catch (NullPointerException ex) {
29             System.out.println("caught exception thrown during clinit");
30         }
31     }
32 
throwDuringClinit()33     private static void throwDuringClinit() {
34         throw new NullPointerException();
35     }
36 
main(String[] args)37     public static void main(String[] args) {
38         checkExceptions();
39         checkTiming();
40         checkStaticMethodInvokeAfterFailedClinit();
41     }
42 
sleep(int msec)43     public static void sleep(int msec) {
44         try {
45             Thread.sleep(msec);
46         } catch (InterruptedException ie) {
47             System.err.println("sleep interrupted");
48         }
49     }
50 
checkExceptions()51     static void checkExceptions() {
52         try {
53             System.out.println(PartialInit.FIELD0);
54             System.err.println("Construction of PartialInit succeeded unexpectedly");
55         } catch (ExceptionInInitializerError eiie) {
56             System.out.println("Got expected EIIE for FIELD0");
57         }
58 
59         try {
60             System.out.println(PartialInit.FIELD0);
61             System.err.println("Load of FIELD0 succeeded unexpectedly");
62         } catch (NoClassDefFoundError ncdfe) {
63             System.out.println("Got expected NCDFE for FIELD0");
64         }
65         try {
66             System.out.println(PartialInit.FIELD1);
67             System.err.println("Load of FIELD1 succeeded unexpectedly");
68         } catch (NoClassDefFoundError ncdfe) {
69             System.out.println("Got expected NCDFE for FIELD1");
70         }
71 
72         try {
73             System.out.println(Exploder.FIELD);
74             System.err.println("Load of FIELD succeeded unexpectedly");
75         } catch (AssertionError expected) {
76             System.out.println("Got expected '" + expected.getMessage() + "' from Exploder");
77         }
78     }
79 
checkTiming()80     static void checkTiming() {
81         FieldThread fieldThread = new FieldThread();
82         MethodThread methodThread = new MethodThread();
83 
84         fieldThread.start();
85         methodThread.start();
86 
87         /* start class init */
88         IntHolder zero = SlowInit.FIELD0;
89 
90         /* wait for children to complete */
91         try {
92             fieldThread.join();
93             methodThread.join();
94         } catch (InterruptedException ie) {
95             System.err.println(ie);
96         }
97 
98         /* print all values */
99         System.out.println("Fields (main thread): " +
100             SlowInit.FIELD0.getValue() + SlowInit.FIELD1.getValue() +
101             SlowInit.FIELD2.getValue() + SlowInit.FIELD3.getValue());
102     }
103 
104     static class FieldThread extends Thread {
run()105         public void run() {
106             /* allow SlowInit's <clinit> to start */
107             Main.sleep(5000);
108 
109             /* collect fields; should delay until class init completes */
110             int field0, field1, field2, field3;
111             field0 = SlowInit.FIELD0.getValue();
112             field1 = SlowInit.FIELD1.getValue();
113             field2 = SlowInit.FIELD2.getValue();
114             field3 = SlowInit.FIELD3.getValue();
115 
116             /* let MethodThread print first */
117             Main.sleep(5000);
118             System.out.println("Fields (child thread): " +
119                 field0 + field1 + field2 + field3);
120         }
121     }
122 
123     static class MethodThread extends Thread {
run()124         public void run() {
125             /* allow SlowInit's <clinit> to start */
126             Main.sleep(5000);
127 
128             /* use a method that shouldn't be accessible yet */
129             SlowInit.printMsg("MethodThread message");
130         }
131     }
132 
checkStaticMethodInvokeAfterFailedClinit()133     static void checkStaticMethodInvokeAfterFailedClinit() {
134         System.out.println("checkStaticMethodInvokeAfterFailedClinit START");
135 
136         // Call static method to cause implicit clinit.
137         try {
138             ClassWithThrowingClinit.staticMethod();
139             System.out.println("checkStaticMethodInvokeAfterFailedClinit FAILED"
140                                + " due to missing ExceptionInInitializerError");
141         } catch (ExceptionInInitializerError expected) {
142         }
143 
144         // Call again to make sure we still get the expected error.
145         try {
146             ClassWithThrowingClinit.staticMethod();
147             System.out.println("checkStaticMethodInvokeAfterFailedClinit FAILED"
148                                + " due to missing NoClassDefFoundError");
149         } catch (NoClassDefFoundError expected) {
150         }
151         System.out.println("checkStaticMethodInvokeAfterFailedClinit PASSED");
152     }
153 
154     static class ClassWithThrowingClinit {
155         static {
throwDuringClinit()156             throwDuringClinit();
157         }
staticMethod()158         static void staticMethod() {
159         }
160     }
161 }
162