xref: /aosp_15_r20/art/test/912-classes/src-art/art/Test912.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 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 package art;
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker import java.lang.ref.Reference;
20*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Constructor;
21*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Proxy;
22*795d594fSAndroid Build Coastguard Worker import java.nio.ByteBuffer;
23*795d594fSAndroid Build Coastguard Worker import java.util.ArrayList;
24*795d594fSAndroid Build Coastguard Worker import java.util.Arrays;
25*795d594fSAndroid Build Coastguard Worker import java.util.Base64;
26*795d594fSAndroid Build Coastguard Worker import java.util.Comparator;
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker public class Test912 {
run()29*795d594fSAndroid Build Coastguard Worker   public static void run() throws Exception {
30*795d594fSAndroid Build Coastguard Worker     doTest();
31*795d594fSAndroid Build Coastguard Worker   }
32*795d594fSAndroid Build Coastguard Worker 
doTest()33*795d594fSAndroid Build Coastguard Worker   public static void doTest() throws Exception {
34*795d594fSAndroid Build Coastguard Worker     testClass("java.lang.Object");
35*795d594fSAndroid Build Coastguard Worker     testClass("java.lang.String");
36*795d594fSAndroid Build Coastguard Worker     testClass("java.lang.Math");
37*795d594fSAndroid Build Coastguard Worker     testClass("java.util.List");
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker     testClass(getProxyClass());
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker     testClass(int.class);
42*795d594fSAndroid Build Coastguard Worker     testClass(double[].class);
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker     testClassType(int.class);
45*795d594fSAndroid Build Coastguard Worker     testClassType(getProxyClass());
46*795d594fSAndroid Build Coastguard Worker     testClassType(Runnable.class);
47*795d594fSAndroid Build Coastguard Worker     testClassType(String.class);
48*795d594fSAndroid Build Coastguard Worker     testClassType(ArrayList.class);
49*795d594fSAndroid Build Coastguard Worker 
50*795d594fSAndroid Build Coastguard Worker     testClassType(int[].class);
51*795d594fSAndroid Build Coastguard Worker     testClassType(Runnable[].class);
52*795d594fSAndroid Build Coastguard Worker     testClassType(String[].class);
53*795d594fSAndroid Build Coastguard Worker 
54*795d594fSAndroid Build Coastguard Worker     testClassFields(Integer.class);
55*795d594fSAndroid Build Coastguard Worker     testClassFields(int.class);
56*795d594fSAndroid Build Coastguard Worker     testClassFields(String[].class);
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker     testClassMethods(Integer.class);
59*795d594fSAndroid Build Coastguard Worker     testClassMethods(int.class);
60*795d594fSAndroid Build Coastguard Worker     testClassMethods(String[].class);
61*795d594fSAndroid Build Coastguard Worker 
62*795d594fSAndroid Build Coastguard Worker     testClassStatus(int.class);
63*795d594fSAndroid Build Coastguard Worker     testClassStatus(String[].class);
64*795d594fSAndroid Build Coastguard Worker     testClassStatus(Object.class);
65*795d594fSAndroid Build Coastguard Worker     testClassStatus(TestForNonInit.class);
66*795d594fSAndroid Build Coastguard Worker     try {
67*795d594fSAndroid Build Coastguard Worker       System.out.println(TestForInitFail.intValue);
68*795d594fSAndroid Build Coastguard Worker     } catch (ExceptionInInitializerError e) {
69*795d594fSAndroid Build Coastguard Worker     }
70*795d594fSAndroid Build Coastguard Worker     testClassStatus(TestForInitFail.class);
71*795d594fSAndroid Build Coastguard Worker 
72*795d594fSAndroid Build Coastguard Worker     testInterfaces(int.class);
73*795d594fSAndroid Build Coastguard Worker     testInterfaces(String[].class);
74*795d594fSAndroid Build Coastguard Worker     testInterfaces(Object.class);
75*795d594fSAndroid Build Coastguard Worker     testInterfaces(InfA.class);
76*795d594fSAndroid Build Coastguard Worker     testInterfaces(InfB.class);
77*795d594fSAndroid Build Coastguard Worker     testInterfaces(InfC.class);
78*795d594fSAndroid Build Coastguard Worker     testInterfaces(ClassA.class);
79*795d594fSAndroid Build Coastguard Worker     testInterfaces(ClassB.class);
80*795d594fSAndroid Build Coastguard Worker     testInterfaces(ClassC.class);
81*795d594fSAndroid Build Coastguard Worker 
82*795d594fSAndroid Build Coastguard Worker     testClassLoader(String.class);
83*795d594fSAndroid Build Coastguard Worker     testClassLoader(String[].class);
84*795d594fSAndroid Build Coastguard Worker     testClassLoader(InfA.class);
85*795d594fSAndroid Build Coastguard Worker     testClassLoader(getProxyClass());
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker     testClassLoaderClasses();
88*795d594fSAndroid Build Coastguard Worker 
89*795d594fSAndroid Build Coastguard Worker     System.out.println();
90*795d594fSAndroid Build Coastguard Worker 
91*795d594fSAndroid Build Coastguard Worker     testClassVersion();
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker     System.out.println();
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker     // Use a dedicated thread to have a well-defined current thread.
96*795d594fSAndroid Build Coastguard Worker     Thread classEventsThread = new Thread("ClassEvents") {
97*795d594fSAndroid Build Coastguard Worker       @Override
98*795d594fSAndroid Build Coastguard Worker       public void run() {
99*795d594fSAndroid Build Coastguard Worker         try {
100*795d594fSAndroid Build Coastguard Worker           testClassEvents();
101*795d594fSAndroid Build Coastguard Worker         } catch (Exception e) {
102*795d594fSAndroid Build Coastguard Worker           throw new RuntimeException(e);
103*795d594fSAndroid Build Coastguard Worker         }
104*795d594fSAndroid Build Coastguard Worker       }
105*795d594fSAndroid Build Coastguard Worker     };
106*795d594fSAndroid Build Coastguard Worker     classEventsThread.start();
107*795d594fSAndroid Build Coastguard Worker     classEventsThread.join();
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker     // b/146170757
110*795d594fSAndroid Build Coastguard Worker     TestRecursiveClassPrepareEvents();
111*795d594fSAndroid Build Coastguard Worker   }
112*795d594fSAndroid Build Coastguard Worker 
testClass(String className)113*795d594fSAndroid Build Coastguard Worker   private static void testClass(String className) throws Exception {
114*795d594fSAndroid Build Coastguard Worker     Class<?> base = Class.forName(className);
115*795d594fSAndroid Build Coastguard Worker     testClass(base);
116*795d594fSAndroid Build Coastguard Worker   }
117*795d594fSAndroid Build Coastguard Worker 
testClass(Class<?> base)118*795d594fSAndroid Build Coastguard Worker   private static void testClass(Class<?> base) throws Exception {
119*795d594fSAndroid Build Coastguard Worker     String[] result = getClassSignature(base);
120*795d594fSAndroid Build Coastguard Worker     System.out.println(Arrays.toString(result));
121*795d594fSAndroid Build Coastguard Worker     int mod = getClassModifiers(base);
122*795d594fSAndroid Build Coastguard Worker     if (mod != base.getModifiers()) {
123*795d594fSAndroid Build Coastguard Worker       throw new RuntimeException("Unexpected modifiers: " + base.getModifiers() + " vs " + mod);
124*795d594fSAndroid Build Coastguard Worker     }
125*795d594fSAndroid Build Coastguard Worker     System.out.println(Integer.toHexString(mod));
126*795d594fSAndroid Build Coastguard Worker   }
127*795d594fSAndroid Build Coastguard Worker 
testClassType(Class<?> c)128*795d594fSAndroid Build Coastguard Worker   private static void testClassType(Class<?> c) throws Exception {
129*795d594fSAndroid Build Coastguard Worker     boolean isInterface = isInterface(c);
130*795d594fSAndroid Build Coastguard Worker     boolean isArray = isArrayClass(c);
131*795d594fSAndroid Build Coastguard Worker     boolean isModifiable = isModifiableClass(c);
132*795d594fSAndroid Build Coastguard Worker     System.out.println(c.getName() + " interface=" + isInterface + " array=" + isArray +
133*795d594fSAndroid Build Coastguard Worker         " modifiable=" + isModifiable);
134*795d594fSAndroid Build Coastguard Worker   }
135*795d594fSAndroid Build Coastguard Worker 
testClassFields(Class<?> c)136*795d594fSAndroid Build Coastguard Worker   private static void testClassFields(Class<?> c) throws Exception {
137*795d594fSAndroid Build Coastguard Worker     System.out.println(Arrays.toString(getClassFields(c)));
138*795d594fSAndroid Build Coastguard Worker   }
139*795d594fSAndroid Build Coastguard Worker 
testClassMethods(Class<?> c)140*795d594fSAndroid Build Coastguard Worker   private static void testClassMethods(Class<?> c) throws Exception {
141*795d594fSAndroid Build Coastguard Worker     System.out.println(Arrays.toString(getClassMethods(c)));
142*795d594fSAndroid Build Coastguard Worker   }
143*795d594fSAndroid Build Coastguard Worker 
testClassStatus(Class<?> c)144*795d594fSAndroid Build Coastguard Worker   private static void testClassStatus(Class<?> c) {
145*795d594fSAndroid Build Coastguard Worker     System.out.println(c + " " + Integer.toBinaryString(getClassStatus(c)));
146*795d594fSAndroid Build Coastguard Worker   }
147*795d594fSAndroid Build Coastguard Worker 
testInterfaces(Class<?> c)148*795d594fSAndroid Build Coastguard Worker   private static void testInterfaces(Class<?> c) {
149*795d594fSAndroid Build Coastguard Worker     System.out.println(c + " " + Arrays.toString(getImplementedInterfaces(c)));
150*795d594fSAndroid Build Coastguard Worker   }
151*795d594fSAndroid Build Coastguard Worker 
IsBootClassLoader(ClassLoader l)152*795d594fSAndroid Build Coastguard Worker   private static boolean IsBootClassLoader(ClassLoader l) {
153*795d594fSAndroid Build Coastguard Worker     // Hacky check for Android's fake boot classloader.
154*795d594fSAndroid Build Coastguard Worker     return l.getClass().getName().equals("java.lang.BootClassLoader");
155*795d594fSAndroid Build Coastguard Worker   }
156*795d594fSAndroid Build Coastguard Worker 
testClassLoader(Class<?> c)157*795d594fSAndroid Build Coastguard Worker   private static void testClassLoader(Class<?> c) {
158*795d594fSAndroid Build Coastguard Worker     Object cl = getClassLoader(c);
159*795d594fSAndroid Build Coastguard Worker     System.out.println(c + " " + (cl != null ? cl.getClass().getName() : "null"));
160*795d594fSAndroid Build Coastguard Worker     if (cl == null) {
161*795d594fSAndroid Build Coastguard Worker       if (c.getClassLoader() != null && !IsBootClassLoader(c.getClassLoader())) {
162*795d594fSAndroid Build Coastguard Worker         throw new RuntimeException("Expected " + c.getClassLoader() + ", but got null.");
163*795d594fSAndroid Build Coastguard Worker       }
164*795d594fSAndroid Build Coastguard Worker     } else {
165*795d594fSAndroid Build Coastguard Worker       if (!(cl instanceof ClassLoader)) {
166*795d594fSAndroid Build Coastguard Worker         throw new RuntimeException("Unexpected \"classloader\": " + cl + " (" + cl.getClass() +
167*795d594fSAndroid Build Coastguard Worker             ")");
168*795d594fSAndroid Build Coastguard Worker       }
169*795d594fSAndroid Build Coastguard Worker       if (cl != c.getClassLoader()) {
170*795d594fSAndroid Build Coastguard Worker         throw new RuntimeException("Unexpected classloader: " + c.getClassLoader() + " vs " + cl);
171*795d594fSAndroid Build Coastguard Worker       }
172*795d594fSAndroid Build Coastguard Worker     }
173*795d594fSAndroid Build Coastguard Worker   }
174*795d594fSAndroid Build Coastguard Worker 
testClassLoaderClasses()175*795d594fSAndroid Build Coastguard Worker   private static void testClassLoaderClasses() throws Exception {
176*795d594fSAndroid Build Coastguard Worker     System.out.println();
177*795d594fSAndroid Build Coastguard Worker     System.out.println("boot <- (B) <- (A,C)");
178*795d594fSAndroid Build Coastguard Worker     ClassLoader cl1 = DexData.create2(DexData.create1());
179*795d594fSAndroid Build Coastguard Worker     Class.forName("B", false, cl1);
180*795d594fSAndroid Build Coastguard Worker     Class.forName("A", false, cl1);
181*795d594fSAndroid Build Coastguard Worker     printClassLoaderClasses(cl1);
182*795d594fSAndroid Build Coastguard Worker 
183*795d594fSAndroid Build Coastguard Worker     System.out.println();
184*795d594fSAndroid Build Coastguard Worker     System.out.println("boot <- (B) <- (A, List)");
185*795d594fSAndroid Build Coastguard Worker     ClassLoader cl2 = DexData.create2(DexData.create1());
186*795d594fSAndroid Build Coastguard Worker     Class.forName("A", false, cl2);
187*795d594fSAndroid Build Coastguard Worker     Class.forName("java.util.List", false, cl2);
188*795d594fSAndroid Build Coastguard Worker     Class.forName("B", false, cl2.getParent());
189*795d594fSAndroid Build Coastguard Worker     printClassLoaderClasses(cl2);
190*795d594fSAndroid Build Coastguard Worker 
191*795d594fSAndroid Build Coastguard Worker     System.out.println();
192*795d594fSAndroid Build Coastguard Worker     System.out.println("boot <- 1+2 (A,B)");
193*795d594fSAndroid Build Coastguard Worker     ClassLoader cl3 = DexData.create12();
194*795d594fSAndroid Build Coastguard Worker     Class.forName("B", false, cl3);
195*795d594fSAndroid Build Coastguard Worker     Class.forName("A", false, cl3);
196*795d594fSAndroid Build Coastguard Worker     printClassLoaderClasses(cl3);
197*795d594fSAndroid Build Coastguard Worker 
198*795d594fSAndroid Build Coastguard Worker     // Check that the boot classloader dumps something non-empty.
199*795d594fSAndroid Build Coastguard Worker     ClassLoader boot = ClassLoader.getSystemClassLoader().getParent();
200*795d594fSAndroid Build Coastguard Worker     while (boot.getParent() != null) {
201*795d594fSAndroid Build Coastguard Worker       boot = boot.getParent();
202*795d594fSAndroid Build Coastguard Worker     }
203*795d594fSAndroid Build Coastguard Worker 
204*795d594fSAndroid Build Coastguard Worker     Class<?>[] bootClasses = getClassLoaderClasses(boot);
205*795d594fSAndroid Build Coastguard Worker     if (bootClasses.length == 0) {
206*795d594fSAndroid Build Coastguard Worker       throw new RuntimeException("No classes initiated by boot classloader.");
207*795d594fSAndroid Build Coastguard Worker     }
208*795d594fSAndroid Build Coastguard Worker     // Check that at least java.util.List is loaded.
209*795d594fSAndroid Build Coastguard Worker     boolean foundList = false;
210*795d594fSAndroid Build Coastguard Worker     for (Class<?> c : bootClasses) {
211*795d594fSAndroid Build Coastguard Worker       if (c == java.util.List.class) {
212*795d594fSAndroid Build Coastguard Worker         foundList = true;
213*795d594fSAndroid Build Coastguard Worker         break;
214*795d594fSAndroid Build Coastguard Worker       }
215*795d594fSAndroid Build Coastguard Worker     }
216*795d594fSAndroid Build Coastguard Worker     if (!foundList) {
217*795d594fSAndroid Build Coastguard Worker       System.out.println(Arrays.toString(bootClasses));
218*795d594fSAndroid Build Coastguard Worker       throw new RuntimeException("Could not find class java.util.List.");
219*795d594fSAndroid Build Coastguard Worker     }
220*795d594fSAndroid Build Coastguard Worker   }
221*795d594fSAndroid Build Coastguard Worker 
222*795d594fSAndroid Build Coastguard Worker   /**
223*795d594fSAndroid Build Coastguard Worker    * base64 encoded class/dex file for
224*795d594fSAndroid Build Coastguard Worker    * class Transform {
225*795d594fSAndroid Build Coastguard Worker    *   public void sayHi() {
226*795d594fSAndroid Build Coastguard Worker    *    System.out.println("Goodbye");
227*795d594fSAndroid Build Coastguard Worker    *   }
228*795d594fSAndroid Build Coastguard Worker    * }
229*795d594fSAndroid Build Coastguard Worker    */
230*795d594fSAndroid Build Coastguard Worker   private static final byte[] DEX_BYTES = Base64.getDecoder().decode(
231*795d594fSAndroid Build Coastguard Worker     "ZGV4CjAzNQCLXSBQ5FiS3f16krSYZFF8xYZtFVp0GRXMAgAAcAAAAHhWNBIAAAAAAAAAACwCAAAO" +
232*795d594fSAndroid Build Coastguard Worker     "AAAAcAAAAAYAAACoAAAAAgAAAMAAAAABAAAA2AAAAAQAAADgAAAAAQAAAAABAACsAQAAIAEAAGIB" +
233*795d594fSAndroid Build Coastguard Worker     "AABqAQAAcwEAAIABAACXAQAAqwEAAL8BAADTAQAA4wEAAOYBAADqAQAA/gEAAAMCAAAMAgAAAgAA" +
234*795d594fSAndroid Build Coastguard Worker     "AAMAAAAEAAAABQAAAAYAAAAIAAAACAAAAAUAAAAAAAAACQAAAAUAAABcAQAABAABAAsAAAAAAAAA" +
235*795d594fSAndroid Build Coastguard Worker     "AAAAAAAAAAANAAAAAQABAAwAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAHAAAAAAAAAB4CAAAA" +
236*795d594fSAndroid Build Coastguard Worker     "AAAAAQABAAEAAAATAgAABAAAAHAQAwAAAA4AAwABAAIAAAAYAgAACQAAAGIAAAAbAQEAAABuIAIA" +
237*795d594fSAndroid Build Coastguard Worker     "EAAOAAAAAQAAAAMABjxpbml0PgAHR29vZGJ5ZQALTFRyYW5zZm9ybTsAFUxqYXZhL2lvL1ByaW50" +
238*795d594fSAndroid Build Coastguard Worker     "U3RyZWFtOwASTGphdmEvbGFuZy9PYmplY3Q7ABJMamF2YS9sYW5nL1N0cmluZzsAEkxqYXZhL2xh" +
239*795d594fSAndroid Build Coastguard Worker     "bmcvU3lzdGVtOwAOVHJhbnNmb3JtLmphdmEAAVYAAlZMABJlbWl0dGVyOiBqYWNrLTMuMzYAA291" +
240*795d594fSAndroid Build Coastguard Worker     "dAAHcHJpbnRsbgAFc2F5SGkAEQAHDgATAAcOhQAAAAEBAICABKACAQG4Ag0AAAAAAAAAAQAAAAAA" +
241*795d594fSAndroid Build Coastguard Worker     "AAABAAAADgAAAHAAAAACAAAABgAAAKgAAAADAAAAAgAAAMAAAAAEAAAAAQAAANgAAAAFAAAABAAA" +
242*795d594fSAndroid Build Coastguard Worker     "AOAAAAAGAAAAAQAAAAABAAABIAAAAgAAACABAAABEAAAAQAAAFwBAAACIAAADgAAAGIBAAADIAAA" +
243*795d594fSAndroid Build Coastguard Worker     "AgAAABMCAAAAIAAAAQAAAB4CAAAAEAAAAQAAACwCAAA=");
testClassVersion()244*795d594fSAndroid Build Coastguard Worker   private static void testClassVersion() throws Exception {
245*795d594fSAndroid Build Coastguard Worker     Class<?> class_loader_class = Class.forName("dalvik.system.InMemoryDexClassLoader");
246*795d594fSAndroid Build Coastguard Worker     Constructor<?> ctor = class_loader_class.getConstructor(ByteBuffer.class, ClassLoader.class);
247*795d594fSAndroid Build Coastguard Worker     Class target = ((ClassLoader)ctor.newInstance(
248*795d594fSAndroid Build Coastguard Worker         ByteBuffer.wrap(DEX_BYTES), Test912.class.getClassLoader())).loadClass("Transform");
249*795d594fSAndroid Build Coastguard Worker     System.out.println(Arrays.toString(getClassVersion(target)));
250*795d594fSAndroid Build Coastguard Worker   }
251*795d594fSAndroid Build Coastguard Worker 
testClassEvents()252*795d594fSAndroid Build Coastguard Worker   private static void testClassEvents() throws Exception {
253*795d594fSAndroid Build Coastguard Worker     ClassLoader cl = Main.class.getClassLoader();
254*795d594fSAndroid Build Coastguard Worker     while (cl.getParent() != null) {
255*795d594fSAndroid Build Coastguard Worker       cl = cl.getParent();
256*795d594fSAndroid Build Coastguard Worker     }
257*795d594fSAndroid Build Coastguard Worker     final ClassLoader boot = cl;
258*795d594fSAndroid Build Coastguard Worker 
259*795d594fSAndroid Build Coastguard Worker     // The JIT may deeply inline and load some classes. Preload these for test determinism.
260*795d594fSAndroid Build Coastguard Worker     final String PRELOAD_FOR_JIT[] = {
261*795d594fSAndroid Build Coastguard Worker         "java.nio.charset.CoderMalfunctionError",
262*795d594fSAndroid Build Coastguard Worker         "java.util.NoSuchElementException",
263*795d594fSAndroid Build Coastguard Worker         "java.io.FileNotFoundException",  // b/63581208
264*795d594fSAndroid Build Coastguard Worker         "java.util.zip.ZipException",     // b/63581208
265*795d594fSAndroid Build Coastguard Worker         "sun.invoke.util.Wrapper",        // For "ClassEvents" thread in JIT/no-image config.
266*795d594fSAndroid Build Coastguard Worker     };
267*795d594fSAndroid Build Coastguard Worker     for (String s : PRELOAD_FOR_JIT) {
268*795d594fSAndroid Build Coastguard Worker       Class.forName(s);
269*795d594fSAndroid Build Coastguard Worker     }
270*795d594fSAndroid Build Coastguard Worker 
271*795d594fSAndroid Build Coastguard Worker     Runnable r = new Runnable() {
272*795d594fSAndroid Build Coastguard Worker       @Override
273*795d594fSAndroid Build Coastguard Worker       public void run() {
274*795d594fSAndroid Build Coastguard Worker         try {
275*795d594fSAndroid Build Coastguard Worker           ClassLoader cl6 = DexData.create12();
276*795d594fSAndroid Build Coastguard Worker           System.out.println("C, true");
277*795d594fSAndroid Build Coastguard Worker           Class.forName("C", true, cl6);
278*795d594fSAndroid Build Coastguard Worker           printClassLoadMessages();
279*795d594fSAndroid Build Coastguard Worker         } catch (Exception e) {
280*795d594fSAndroid Build Coastguard Worker           throw new RuntimeException(e);
281*795d594fSAndroid Build Coastguard Worker         }
282*795d594fSAndroid Build Coastguard Worker       }
283*795d594fSAndroid Build Coastguard Worker     };
284*795d594fSAndroid Build Coastguard Worker 
285*795d594fSAndroid Build Coastguard Worker     Thread noopThread = new Thread();
286*795d594fSAndroid Build Coastguard Worker     noopThread.start();
287*795d594fSAndroid Build Coastguard Worker     noopThread.join();
288*795d594fSAndroid Build Coastguard Worker 
289*795d594fSAndroid Build Coastguard Worker     enableClassLoadPreparePrintEvents(true, Thread.currentThread());
290*795d594fSAndroid Build Coastguard Worker 
291*795d594fSAndroid Build Coastguard Worker     ClassLoader cl1 = DexData.create12();
292*795d594fSAndroid Build Coastguard Worker     System.out.println("B, false");
293*795d594fSAndroid Build Coastguard Worker     Class.forName("B", false, cl1);
294*795d594fSAndroid Build Coastguard Worker     printClassLoadMessages();
295*795d594fSAndroid Build Coastguard Worker 
296*795d594fSAndroid Build Coastguard Worker     ClassLoader cl2 = DexData.create12();
297*795d594fSAndroid Build Coastguard Worker     System.out.println("B, true");
298*795d594fSAndroid Build Coastguard Worker     Class.forName("B", true, cl2);
299*795d594fSAndroid Build Coastguard Worker     printClassLoadMessages();
300*795d594fSAndroid Build Coastguard Worker 
301*795d594fSAndroid Build Coastguard Worker     ClassLoader cl3 = DexData.create12();
302*795d594fSAndroid Build Coastguard Worker     System.out.println("C, false");
303*795d594fSAndroid Build Coastguard Worker     Class.forName("C", false, cl3);
304*795d594fSAndroid Build Coastguard Worker     printClassLoadMessages();
305*795d594fSAndroid Build Coastguard Worker     System.out.println("A, false");
306*795d594fSAndroid Build Coastguard Worker     Class.forName("A", false, cl3);
307*795d594fSAndroid Build Coastguard Worker     printClassLoadMessages();
308*795d594fSAndroid Build Coastguard Worker 
309*795d594fSAndroid Build Coastguard Worker     ClassLoader cl4 = DexData.create12();
310*795d594fSAndroid Build Coastguard Worker     System.out.println("C, true");
311*795d594fSAndroid Build Coastguard Worker     Class.forName("C", true, cl4);
312*795d594fSAndroid Build Coastguard Worker     printClassLoadMessages();
313*795d594fSAndroid Build Coastguard Worker     System.out.println("A, true");
314*795d594fSAndroid Build Coastguard Worker     Class.forName("A", true, cl4);
315*795d594fSAndroid Build Coastguard Worker     printClassLoadMessages();
316*795d594fSAndroid Build Coastguard Worker 
317*795d594fSAndroid Build Coastguard Worker     ClassLoader cl5 = DexData.create12();
318*795d594fSAndroid Build Coastguard Worker     System.out.println("A, true");
319*795d594fSAndroid Build Coastguard Worker     Class.forName("A", true, cl5);
320*795d594fSAndroid Build Coastguard Worker     printClassLoadMessages();
321*795d594fSAndroid Build Coastguard Worker     System.out.println("C, true");
322*795d594fSAndroid Build Coastguard Worker     Class.forName("C", true, cl5);
323*795d594fSAndroid Build Coastguard Worker     printClassLoadMessages();
324*795d594fSAndroid Build Coastguard Worker 
325*795d594fSAndroid Build Coastguard Worker     enableClassLoadPreparePrintEvents(false, null);
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker     Thread t = new Thread(r, "TestRunner");
328*795d594fSAndroid Build Coastguard Worker     enableClassLoadPreparePrintEvents(true, t);
329*795d594fSAndroid Build Coastguard Worker     t.start();
330*795d594fSAndroid Build Coastguard Worker     t.join();
331*795d594fSAndroid Build Coastguard Worker     enableClassLoadPreparePrintEvents(false, null);
332*795d594fSAndroid Build Coastguard Worker 
333*795d594fSAndroid Build Coastguard Worker     enableClassLoadPreparePrintEvents(true, Thread.currentThread());
334*795d594fSAndroid Build Coastguard Worker 
335*795d594fSAndroid Build Coastguard Worker     // Check creation of arrays and proxies.
336*795d594fSAndroid Build Coastguard Worker     Proxy.getProxyClass(Main.class.getClassLoader(), new Class[] { Comparable.class, I0.class });
337*795d594fSAndroid Build Coastguard Worker     Class.forName("[Lart.Test912;");
338*795d594fSAndroid Build Coastguard Worker     printClassLoadMessages();
339*795d594fSAndroid Build Coastguard Worker 
340*795d594fSAndroid Build Coastguard Worker     enableClassLoadPreparePrintEvents(false, null);
341*795d594fSAndroid Build Coastguard Worker 
342*795d594fSAndroid Build Coastguard Worker     testClassLoadPrepareEquality();
343*795d594fSAndroid Build Coastguard Worker   }
344*795d594fSAndroid Build Coastguard Worker 
testClassLoadPrepareEquality()345*795d594fSAndroid Build Coastguard Worker   private static void testClassLoadPrepareEquality() throws Exception {
346*795d594fSAndroid Build Coastguard Worker     setEqualityEventStorageClass(ClassF.class);
347*795d594fSAndroid Build Coastguard Worker 
348*795d594fSAndroid Build Coastguard Worker     enableClassLoadPrepareEqualityEvents(true);
349*795d594fSAndroid Build Coastguard Worker 
350*795d594fSAndroid Build Coastguard Worker     Class.forName("art.Test912$ClassE");
351*795d594fSAndroid Build Coastguard Worker 
352*795d594fSAndroid Build Coastguard Worker     enableClassLoadPrepareEqualityEvents(false);
353*795d594fSAndroid Build Coastguard Worker   }
354*795d594fSAndroid Build Coastguard Worker 
printClassLoaderClasses(ClassLoader cl)355*795d594fSAndroid Build Coastguard Worker   private static void printClassLoaderClasses(ClassLoader cl) {
356*795d594fSAndroid Build Coastguard Worker     for (;;) {
357*795d594fSAndroid Build Coastguard Worker       if (cl == null || !cl.getClass().getName().startsWith("dalvik.system")) {
358*795d594fSAndroid Build Coastguard Worker         break;
359*795d594fSAndroid Build Coastguard Worker       }
360*795d594fSAndroid Build Coastguard Worker 
361*795d594fSAndroid Build Coastguard Worker       Class<?> classes[] = getClassLoaderClasses(cl);
362*795d594fSAndroid Build Coastguard Worker       Arrays.sort(classes, new ClassNameComparator());
363*795d594fSAndroid Build Coastguard Worker       System.out.println(Arrays.toString(classes));
364*795d594fSAndroid Build Coastguard Worker 
365*795d594fSAndroid Build Coastguard Worker       cl = cl.getParent();
366*795d594fSAndroid Build Coastguard Worker     }
367*795d594fSAndroid Build Coastguard Worker   }
368*795d594fSAndroid Build Coastguard Worker 
printClassLoadMessages()369*795d594fSAndroid Build Coastguard Worker   private static void printClassLoadMessages() {
370*795d594fSAndroid Build Coastguard Worker     for (String s : getClassLoadMessages()) {
371*795d594fSAndroid Build Coastguard Worker       System.out.println(s);
372*795d594fSAndroid Build Coastguard Worker     }
373*795d594fSAndroid Build Coastguard Worker   }
374*795d594fSAndroid Build Coastguard Worker 
isModifiableClass(Class<?> c)375*795d594fSAndroid Build Coastguard Worker   private static native boolean isModifiableClass(Class<?> c);
getClassSignature(Class<?> c)376*795d594fSAndroid Build Coastguard Worker   private static native String[] getClassSignature(Class<?> c);
377*795d594fSAndroid Build Coastguard Worker 
isInterface(Class<?> c)378*795d594fSAndroid Build Coastguard Worker   private static native boolean isInterface(Class<?> c);
isArrayClass(Class<?> c)379*795d594fSAndroid Build Coastguard Worker   private static native boolean isArrayClass(Class<?> c);
380*795d594fSAndroid Build Coastguard Worker 
getClassModifiers(Class<?> c)381*795d594fSAndroid Build Coastguard Worker   private static native int getClassModifiers(Class<?> c);
382*795d594fSAndroid Build Coastguard Worker 
getClassFields(Class<?> c)383*795d594fSAndroid Build Coastguard Worker   private static native Object[] getClassFields(Class<?> c);
getClassMethods(Class<?> c)384*795d594fSAndroid Build Coastguard Worker   private static native Object[] getClassMethods(Class<?> c);
getImplementedInterfaces(Class<?> c)385*795d594fSAndroid Build Coastguard Worker   private static native Class<?>[] getImplementedInterfaces(Class<?> c);
386*795d594fSAndroid Build Coastguard Worker 
getClassStatus(Class<?> c)387*795d594fSAndroid Build Coastguard Worker   private static native int getClassStatus(Class<?> c);
388*795d594fSAndroid Build Coastguard Worker 
getClassLoader(Class<?> c)389*795d594fSAndroid Build Coastguard Worker   private static native Object getClassLoader(Class<?> c);
390*795d594fSAndroid Build Coastguard Worker 
getClassLoaderClasses(ClassLoader cl)391*795d594fSAndroid Build Coastguard Worker   private static native Class<?>[] getClassLoaderClasses(ClassLoader cl);
392*795d594fSAndroid Build Coastguard Worker 
getClassVersion(Class<?> c)393*795d594fSAndroid Build Coastguard Worker   private static native int[] getClassVersion(Class<?> c);
394*795d594fSAndroid Build Coastguard Worker 
enableClassLoadPreparePrintEvents(boolean b, Thread filter)395*795d594fSAndroid Build Coastguard Worker   private static native void enableClassLoadPreparePrintEvents(boolean b, Thread filter);
getClassLoadMessages()396*795d594fSAndroid Build Coastguard Worker   private static native String[] getClassLoadMessages();
397*795d594fSAndroid Build Coastguard Worker 
setEqualityEventStorageClass(Class<?> c)398*795d594fSAndroid Build Coastguard Worker   private static native void setEqualityEventStorageClass(Class<?> c);
enableClassLoadPrepareEqualityEvents(boolean b)399*795d594fSAndroid Build Coastguard Worker   private static native void enableClassLoadPrepareEqualityEvents(boolean b);
400*795d594fSAndroid Build Coastguard Worker 
runRecursiveClassPrepareEvents(Runnable forceLoad)401*795d594fSAndroid Build Coastguard Worker   private static native void runRecursiveClassPrepareEvents(Runnable forceLoad);
402*795d594fSAndroid Build Coastguard Worker 
TestRecursiveClassPrepareEvents()403*795d594fSAndroid Build Coastguard Worker   private static void TestRecursiveClassPrepareEvents() {
404*795d594fSAndroid Build Coastguard Worker     final int[] called = new int[] { 0 };
405*795d594fSAndroid Build Coastguard Worker     runRecursiveClassPrepareEvents(() -> {
406*795d594fSAndroid Build Coastguard Worker       if (called[0] == 2) {
407*795d594fSAndroid Build Coastguard Worker         return;
408*795d594fSAndroid Build Coastguard Worker       } else {
409*795d594fSAndroid Build Coastguard Worker         called[0]++;
410*795d594fSAndroid Build Coastguard Worker       }
411*795d594fSAndroid Build Coastguard Worker       try {
412*795d594fSAndroid Build Coastguard Worker         System.out.println("class-prepare event START!");
413*795d594fSAndroid Build Coastguard Worker         // Load a new class in a new class-loader.
414*795d594fSAndroid Build Coastguard Worker         Class<?> class_loader_class = Class.forName("dalvik.system.InMemoryDexClassLoader");
415*795d594fSAndroid Build Coastguard Worker         Constructor<?> ctor = class_loader_class.getConstructor(ByteBuffer.class, ClassLoader.class);
416*795d594fSAndroid Build Coastguard Worker         Class<?> target = ((ClassLoader)ctor.newInstance(
417*795d594fSAndroid Build Coastguard Worker             ByteBuffer.wrap(DEX_BYTES), Test912.class.getClassLoader())).loadClass("Transform");
418*795d594fSAndroid Build Coastguard Worker         target.newInstance();
419*795d594fSAndroid Build Coastguard Worker       } catch (Exception e) { }
420*795d594fSAndroid Build Coastguard Worker       System.out.println("class-prepare event END!");
421*795d594fSAndroid Build Coastguard Worker     });
422*795d594fSAndroid Build Coastguard Worker     if (called[0] != 2) {
423*795d594fSAndroid Build Coastguard Worker       System.out.println("Failed to cause recursive Class prepare.");
424*795d594fSAndroid Build Coastguard Worker     }
425*795d594fSAndroid Build Coastguard Worker   }
426*795d594fSAndroid Build Coastguard Worker 
427*795d594fSAndroid Build Coastguard Worker   private static class TestForNonInit {
428*795d594fSAndroid Build Coastguard Worker     public static double doubleValue = Math.random();  // So it can't be compile-time initialized.
429*795d594fSAndroid Build Coastguard Worker   }
430*795d594fSAndroid Build Coastguard Worker 
431*795d594fSAndroid Build Coastguard Worker   @SuppressWarnings("RandomCast")
432*795d594fSAndroid Build Coastguard Worker   private static class TestForInitFail {
433*795d594fSAndroid Build Coastguard Worker     public static int intValue = ((int)Math.random())/0;  // So it throws when initializing.
434*795d594fSAndroid Build Coastguard Worker   }
435*795d594fSAndroid Build Coastguard Worker 
436*795d594fSAndroid Build Coastguard Worker   public static interface InfA {
437*795d594fSAndroid Build Coastguard Worker   }
438*795d594fSAndroid Build Coastguard Worker   public static interface InfB extends InfA {
439*795d594fSAndroid Build Coastguard Worker   }
440*795d594fSAndroid Build Coastguard Worker   public static interface InfC extends InfB {
441*795d594fSAndroid Build Coastguard Worker   }
442*795d594fSAndroid Build Coastguard Worker 
443*795d594fSAndroid Build Coastguard Worker   public abstract static class ClassA implements InfA {
444*795d594fSAndroid Build Coastguard Worker   }
445*795d594fSAndroid Build Coastguard Worker   public abstract static class ClassB extends ClassA implements InfB {
446*795d594fSAndroid Build Coastguard Worker   }
447*795d594fSAndroid Build Coastguard Worker   public abstract static class ClassC implements InfA, InfC {
448*795d594fSAndroid Build Coastguard Worker   }
449*795d594fSAndroid Build Coastguard Worker 
450*795d594fSAndroid Build Coastguard Worker   public static class ClassE {
foo()451*795d594fSAndroid Build Coastguard Worker     public void foo() {
452*795d594fSAndroid Build Coastguard Worker     }
bar()453*795d594fSAndroid Build Coastguard Worker     public void bar() {
454*795d594fSAndroid Build Coastguard Worker     }
455*795d594fSAndroid Build Coastguard Worker   }
456*795d594fSAndroid Build Coastguard Worker 
457*795d594fSAndroid Build Coastguard Worker   public static class ClassF {
458*795d594fSAndroid Build Coastguard Worker     public static Object STATIC = null;
459*795d594fSAndroid Build Coastguard Worker     public static Reference<Object> WEAK = null;
460*795d594fSAndroid Build Coastguard Worker   }
461*795d594fSAndroid Build Coastguard Worker 
462*795d594fSAndroid Build Coastguard Worker   private static class ClassNameComparator implements Comparator<Class<?>> {
compare(Class<?> c1, Class<?> c2)463*795d594fSAndroid Build Coastguard Worker     public int compare(Class<?> c1, Class<?> c2) {
464*795d594fSAndroid Build Coastguard Worker       return c1.getName().compareTo(c2.getName());
465*795d594fSAndroid Build Coastguard Worker     }
466*795d594fSAndroid Build Coastguard Worker   }
467*795d594fSAndroid Build Coastguard Worker 
468*795d594fSAndroid Build Coastguard Worker   // See run-test 910 for an explanation.
469*795d594fSAndroid Build Coastguard Worker 
470*795d594fSAndroid Build Coastguard Worker   private static Class<?> proxyClass = null;
471*795d594fSAndroid Build Coastguard Worker 
getProxyClass()472*795d594fSAndroid Build Coastguard Worker   private static Class<?> getProxyClass() throws Exception {
473*795d594fSAndroid Build Coastguard Worker     if (proxyClass != null) {
474*795d594fSAndroid Build Coastguard Worker       return proxyClass;
475*795d594fSAndroid Build Coastguard Worker     }
476*795d594fSAndroid Build Coastguard Worker 
477*795d594fSAndroid Build Coastguard Worker     for (int i = 1; i <= 21; i++) {
478*795d594fSAndroid Build Coastguard Worker       proxyClass = createProxyClass(i);
479*795d594fSAndroid Build Coastguard Worker       String name = proxyClass.getName();
480*795d594fSAndroid Build Coastguard Worker       if (name.equals("$Proxy20")) {
481*795d594fSAndroid Build Coastguard Worker         return proxyClass;
482*795d594fSAndroid Build Coastguard Worker       }
483*795d594fSAndroid Build Coastguard Worker     }
484*795d594fSAndroid Build Coastguard Worker     return proxyClass;
485*795d594fSAndroid Build Coastguard Worker   }
486*795d594fSAndroid Build Coastguard Worker 
createProxyClass(int i)487*795d594fSAndroid Build Coastguard Worker   private static Class<?> createProxyClass(int i) throws Exception {
488*795d594fSAndroid Build Coastguard Worker     int count = Integer.bitCount(i);
489*795d594fSAndroid Build Coastguard Worker     Class<?>[] input = new Class<?>[count + 1];
490*795d594fSAndroid Build Coastguard Worker     input[0] = Runnable.class;
491*795d594fSAndroid Build Coastguard Worker     int inputIndex = 1;
492*795d594fSAndroid Build Coastguard Worker     int bitIndex = 0;
493*795d594fSAndroid Build Coastguard Worker     while (i != 0) {
494*795d594fSAndroid Build Coastguard Worker         if ((i & 1) != 0) {
495*795d594fSAndroid Build Coastguard Worker             input[inputIndex++] = Class.forName("art.Test912$I" + bitIndex);
496*795d594fSAndroid Build Coastguard Worker         }
497*795d594fSAndroid Build Coastguard Worker         i >>>= 1;
498*795d594fSAndroid Build Coastguard Worker         bitIndex++;
499*795d594fSAndroid Build Coastguard Worker     }
500*795d594fSAndroid Build Coastguard Worker     return Proxy.getProxyClass(Test912.class.getClassLoader(), input);
501*795d594fSAndroid Build Coastguard Worker   }
502*795d594fSAndroid Build Coastguard Worker 
503*795d594fSAndroid Build Coastguard Worker   // Need this for the proxy naming.
504*795d594fSAndroid Build Coastguard Worker   public static interface I0 {
505*795d594fSAndroid Build Coastguard Worker   }
506*795d594fSAndroid Build Coastguard Worker   public static interface I1 {
507*795d594fSAndroid Build Coastguard Worker   }
508*795d594fSAndroid Build Coastguard Worker   public static interface I2 {
509*795d594fSAndroid Build Coastguard Worker   }
510*795d594fSAndroid Build Coastguard Worker   public static interface I3 {
511*795d594fSAndroid Build Coastguard Worker   }
512*795d594fSAndroid Build Coastguard Worker   public static interface I4 {
513*795d594fSAndroid Build Coastguard Worker   }
514*795d594fSAndroid Build Coastguard Worker }
515