xref: /aosp_15_r20/art/test/068-classloader/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2008 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.lang.reflect.Constructor;
18*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method;
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker /**
21*795d594fSAndroid Build Coastguard Worker  * Class loader test.
22*795d594fSAndroid Build Coastguard Worker  */
23*795d594fSAndroid Build Coastguard Worker public class Main {
24*795d594fSAndroid Build Coastguard Worker     /**
25*795d594fSAndroid Build Coastguard Worker      * Main entry point.
26*795d594fSAndroid Build Coastguard Worker      */
main(String[] args)27*795d594fSAndroid Build Coastguard Worker     public static void main(String[] args) throws Exception {
28*795d594fSAndroid Build Coastguard Worker         FancyLoader loader;
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker         loader = new FancyLoader(ClassLoader.getSystemClassLoader());
31*795d594fSAndroid Build Coastguard Worker         //System.out.println("SYSTEM: " + ClassLoader.getSystemClassLoader());
32*795d594fSAndroid Build Coastguard Worker         //System.out.println("ALTERN: " + loader);
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker         /*
35*795d594fSAndroid Build Coastguard Worker          * This statement has no effect on this program, but it can
36*795d594fSAndroid Build Coastguard Worker          * change the point where a LinkageException is thrown in
37*795d594fSAndroid Build Coastguard Worker          * testImplement().  When this is present the "reference
38*795d594fSAndroid Build Coastguard Worker          * implementation" throws an exception from Class.newInstance(),
39*795d594fSAndroid Build Coastguard Worker          * when it's absent the exception is deferred until the first time
40*795d594fSAndroid Build Coastguard Worker          * we call a method that isn't actually implemented.
41*795d594fSAndroid Build Coastguard Worker          *
42*795d594fSAndroid Build Coastguard Worker          * This isn't the class that fails -- it's a class with the same
43*795d594fSAndroid Build Coastguard Worker          * name in the "fancy" class loader --  but the VM thinks it has a
44*795d594fSAndroid Build Coastguard Worker          * reference to one of these; presumably the difference is that
45*795d594fSAndroid Build Coastguard Worker          * without this the VM finds itself holding a reference to an
46*795d594fSAndroid Build Coastguard Worker          * instance of an uninitialized class.
47*795d594fSAndroid Build Coastguard Worker          */
48*795d594fSAndroid Build Coastguard Worker         System.out.println("base: " + DoubledImplement.class);
49*795d594fSAndroid Build Coastguard Worker         System.out.println("base2: " + DoubledImplement2.class);
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker         /*
52*795d594fSAndroid Build Coastguard Worker          * Run tests.
53*795d594fSAndroid Build Coastguard Worker          */
54*795d594fSAndroid Build Coastguard Worker         testAccess1(loader);
55*795d594fSAndroid Build Coastguard Worker         testAccess2(loader);
56*795d594fSAndroid Build Coastguard Worker         testAccess3(loader);
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker         testExtend(loader);
59*795d594fSAndroid Build Coastguard Worker         testExtendOkay(loader);
60*795d594fSAndroid Build Coastguard Worker         testInterface(loader);
61*795d594fSAndroid Build Coastguard Worker         testAbstract(loader);
62*795d594fSAndroid Build Coastguard Worker         testImplement(loader);
63*795d594fSAndroid Build Coastguard Worker         testIfaceImplement(loader);
64*795d594fSAndroid Build Coastguard Worker 
65*795d594fSAndroid Build Coastguard Worker         testSeparation();
66*795d594fSAndroid Build Coastguard Worker 
67*795d594fSAndroid Build Coastguard Worker         testClassForName();
68*795d594fSAndroid Build Coastguard Worker 
69*795d594fSAndroid Build Coastguard Worker         testNullClassLoader();
70*795d594fSAndroid Build Coastguard Worker     }
71*795d594fSAndroid Build Coastguard Worker 
testNullClassLoader()72*795d594fSAndroid Build Coastguard Worker     static void testNullClassLoader() {
73*795d594fSAndroid Build Coastguard Worker         try {
74*795d594fSAndroid Build Coastguard Worker             /* this is the "alternate" DEX/Jar file */
75*795d594fSAndroid Build Coastguard Worker             String DEX_FILE = System.getenv("DEX_LOCATION") + "/068-classloader-ex.jar";
76*795d594fSAndroid Build Coastguard Worker             /* on Dalvik, this is a DexFile; otherwise, it's null */
77*795d594fSAndroid Build Coastguard Worker             Class<?> mDexClass = Class.forName("dalvik.system.DexFile");
78*795d594fSAndroid Build Coastguard Worker             Constructor<?> ctor = mDexClass.getConstructor(String.class);
79*795d594fSAndroid Build Coastguard Worker             Object mDexFile = ctor.newInstance(DEX_FILE);
80*795d594fSAndroid Build Coastguard Worker             Method meth = mDexClass.getMethod("loadClass", String.class, ClassLoader.class);
81*795d594fSAndroid Build Coastguard Worker             Object klass = meth.invoke(mDexFile, "Mutator", null);
82*795d594fSAndroid Build Coastguard Worker             if (klass == null) {
83*795d594fSAndroid Build Coastguard Worker                 throw new AssertionError("loadClass with nullclass loader failed");
84*795d594fSAndroid Build Coastguard Worker             }
85*795d594fSAndroid Build Coastguard Worker         } catch (Exception e) {
86*795d594fSAndroid Build Coastguard Worker             System.out.println(e);
87*795d594fSAndroid Build Coastguard Worker         }
88*795d594fSAndroid Build Coastguard Worker         System.out.println("Loaded class into null class loader");
89*795d594fSAndroid Build Coastguard Worker     }
90*795d594fSAndroid Build Coastguard Worker 
testSeparation()91*795d594fSAndroid Build Coastguard Worker     static void testSeparation() {
92*795d594fSAndroid Build Coastguard Worker         FancyLoader loader1 = new FancyLoader(ClassLoader.getSystemClassLoader());
93*795d594fSAndroid Build Coastguard Worker         FancyLoader loader2 = new FancyLoader(ClassLoader.getSystemClassLoader());
94*795d594fSAndroid Build Coastguard Worker 
95*795d594fSAndroid Build Coastguard Worker         try {
96*795d594fSAndroid Build Coastguard Worker             Class<?> target1 = loader1.loadClass("MutationTarget");
97*795d594fSAndroid Build Coastguard Worker             Class<?> target2 = loader2.loadClass("MutationTarget");
98*795d594fSAndroid Build Coastguard Worker 
99*795d594fSAndroid Build Coastguard Worker             if (target1 == target2) {
100*795d594fSAndroid Build Coastguard Worker                 throw new RuntimeException("target1 should not be equal to target2");
101*795d594fSAndroid Build Coastguard Worker             }
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker             Class<?> mutator1 = loader1.loadClass("Mutator");
104*795d594fSAndroid Build Coastguard Worker             Class<?> mutator2 = loader2.loadClass("Mutator");
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker             if (mutator1 == mutator2) {
107*795d594fSAndroid Build Coastguard Worker                 throw new RuntimeException("mutator1 should not be equal to mutator2");
108*795d594fSAndroid Build Coastguard Worker             }
109*795d594fSAndroid Build Coastguard Worker 
110*795d594fSAndroid Build Coastguard Worker             runMutator(mutator1, 1);
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker             int value = getMutationTargetValue(target1);
113*795d594fSAndroid Build Coastguard Worker             if (value != 1) {
114*795d594fSAndroid Build Coastguard Worker                 throw new RuntimeException("target 1 has unexpected value " + value);
115*795d594fSAndroid Build Coastguard Worker             }
116*795d594fSAndroid Build Coastguard Worker             value = getMutationTargetValue(target2);
117*795d594fSAndroid Build Coastguard Worker             if (value != 0) {
118*795d594fSAndroid Build Coastguard Worker                 throw new RuntimeException("target 2 has unexpected value " + value);
119*795d594fSAndroid Build Coastguard Worker             }
120*795d594fSAndroid Build Coastguard Worker 
121*795d594fSAndroid Build Coastguard Worker             runMutator(mutator2, 2);
122*795d594fSAndroid Build Coastguard Worker 
123*795d594fSAndroid Build Coastguard Worker             value = getMutationTargetValue(target1);
124*795d594fSAndroid Build Coastguard Worker             if (value != 1) {
125*795d594fSAndroid Build Coastguard Worker                 throw new RuntimeException("target 1 has unexpected value " + value);
126*795d594fSAndroid Build Coastguard Worker             }
127*795d594fSAndroid Build Coastguard Worker             value = getMutationTargetValue(target2);
128*795d594fSAndroid Build Coastguard Worker             if (value != 2) {
129*795d594fSAndroid Build Coastguard Worker                 throw new RuntimeException("target 2 has unexpected value " + value);
130*795d594fSAndroid Build Coastguard Worker             }
131*795d594fSAndroid Build Coastguard Worker         } catch (Exception ex) {
132*795d594fSAndroid Build Coastguard Worker             ex.printStackTrace(System.out);
133*795d594fSAndroid Build Coastguard Worker         }
134*795d594fSAndroid Build Coastguard Worker     }
135*795d594fSAndroid Build Coastguard Worker 
runMutator(Class<?> c, int v)136*795d594fSAndroid Build Coastguard Worker     private static void runMutator(Class<?> c, int v) throws Exception {
137*795d594fSAndroid Build Coastguard Worker         java.lang.reflect.Method m = c.getDeclaredMethod("mutate", int.class);
138*795d594fSAndroid Build Coastguard Worker         m.invoke(null, v);
139*795d594fSAndroid Build Coastguard Worker     }
140*795d594fSAndroid Build Coastguard Worker 
getMutationTargetValue(Class<?> c)141*795d594fSAndroid Build Coastguard Worker     private static int getMutationTargetValue(Class<?> c) throws Exception {
142*795d594fSAndroid Build Coastguard Worker         java.lang.reflect.Field f = c.getDeclaredField("value");
143*795d594fSAndroid Build Coastguard Worker         return f.getInt(null);
144*795d594fSAndroid Build Coastguard Worker     }
145*795d594fSAndroid Build Coastguard Worker 
146*795d594fSAndroid Build Coastguard Worker     /**
147*795d594fSAndroid Build Coastguard Worker      * See if we can load a class that isn't public to us.  We should be
148*795d594fSAndroid Build Coastguard Worker      * able to load it but not instantiate it.
149*795d594fSAndroid Build Coastguard Worker      */
testAccess1(ClassLoader loader)150*795d594fSAndroid Build Coastguard Worker     static void testAccess1(ClassLoader loader) {
151*795d594fSAndroid Build Coastguard Worker         Class<?> altClass;
152*795d594fSAndroid Build Coastguard Worker 
153*795d594fSAndroid Build Coastguard Worker         try {
154*795d594fSAndroid Build Coastguard Worker             altClass = loader.loadClass("Inaccessible1");
155*795d594fSAndroid Build Coastguard Worker         } catch (ClassNotFoundException cnfe) {
156*795d594fSAndroid Build Coastguard Worker             System.out.println("loadClass failed");
157*795d594fSAndroid Build Coastguard Worker             cnfe.printStackTrace(System.out);
158*795d594fSAndroid Build Coastguard Worker             return;
159*795d594fSAndroid Build Coastguard Worker         }
160*795d594fSAndroid Build Coastguard Worker 
161*795d594fSAndroid Build Coastguard Worker         /* instantiate */
162*795d594fSAndroid Build Coastguard Worker         Object obj;
163*795d594fSAndroid Build Coastguard Worker         try {
164*795d594fSAndroid Build Coastguard Worker             obj = altClass.newInstance();
165*795d594fSAndroid Build Coastguard Worker             System.out.println("ERROR: Inaccessible1 was accessible");
166*795d594fSAndroid Build Coastguard Worker         } catch (InstantiationException ie) {
167*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + ie);
168*795d594fSAndroid Build Coastguard Worker             return;
169*795d594fSAndroid Build Coastguard Worker         } catch (IllegalAccessException iae) {
170*795d594fSAndroid Build Coastguard Worker             System.out.println("Got expected access exception #1");
171*795d594fSAndroid Build Coastguard Worker             //System.out.println("+++ " + iae);
172*795d594fSAndroid Build Coastguard Worker             return;
173*795d594fSAndroid Build Coastguard Worker         }
174*795d594fSAndroid Build Coastguard Worker     }
175*795d594fSAndroid Build Coastguard Worker 
176*795d594fSAndroid Build Coastguard Worker     /**
177*795d594fSAndroid Build Coastguard Worker      * See if we can load a class whose base class is not accessible to it
178*795d594fSAndroid Build Coastguard Worker      * (though the base *is* accessible to us).
179*795d594fSAndroid Build Coastguard Worker      */
testAccess2(ClassLoader loader)180*795d594fSAndroid Build Coastguard Worker     static void testAccess2(ClassLoader loader) {
181*795d594fSAndroid Build Coastguard Worker         Class<?> altClass;
182*795d594fSAndroid Build Coastguard Worker 
183*795d594fSAndroid Build Coastguard Worker         try {
184*795d594fSAndroid Build Coastguard Worker             altClass = loader.loadClass("Inaccessible2");
185*795d594fSAndroid Build Coastguard Worker             System.out.println("ERROR: Inaccessible2 was accessible: " + altClass);
186*795d594fSAndroid Build Coastguard Worker         } catch (ClassNotFoundException cnfe) {
187*795d594fSAndroid Build Coastguard Worker             Throwable cause = cnfe.getCause();
188*795d594fSAndroid Build Coastguard Worker             if (cause instanceof IllegalAccessError) {
189*795d594fSAndroid Build Coastguard Worker                 System.out.println("Got expected CNFE/IAE #2");
190*795d594fSAndroid Build Coastguard Worker             } else {
191*795d594fSAndroid Build Coastguard Worker                 System.out.println("Got unexpected CNFE/IAE #2");
192*795d594fSAndroid Build Coastguard Worker                 cnfe.printStackTrace(System.out);
193*795d594fSAndroid Build Coastguard Worker             }
194*795d594fSAndroid Build Coastguard Worker         }
195*795d594fSAndroid Build Coastguard Worker     }
196*795d594fSAndroid Build Coastguard Worker 
197*795d594fSAndroid Build Coastguard Worker     /**
198*795d594fSAndroid Build Coastguard Worker      * See if we can load a class with an inaccessible interface.
199*795d594fSAndroid Build Coastguard Worker      */
testAccess3(ClassLoader loader)200*795d594fSAndroid Build Coastguard Worker     static void testAccess3(ClassLoader loader) {
201*795d594fSAndroid Build Coastguard Worker         Class<?> altClass;
202*795d594fSAndroid Build Coastguard Worker 
203*795d594fSAndroid Build Coastguard Worker         try {
204*795d594fSAndroid Build Coastguard Worker             altClass = loader.loadClass("Inaccessible3");
205*795d594fSAndroid Build Coastguard Worker             System.out.println("ERROR: Inaccessible3 was accessible: " + altClass);
206*795d594fSAndroid Build Coastguard Worker         } catch (ClassNotFoundException cnfe) {
207*795d594fSAndroid Build Coastguard Worker             Throwable cause = cnfe.getCause();
208*795d594fSAndroid Build Coastguard Worker             if (cause instanceof IllegalAccessError) {
209*795d594fSAndroid Build Coastguard Worker                 System.out.println("Got expected CNFE/IAE #3");
210*795d594fSAndroid Build Coastguard Worker             } else {
211*795d594fSAndroid Build Coastguard Worker                 System.out.println("Got unexpected CNFE/IAE #3");
212*795d594fSAndroid Build Coastguard Worker                 cnfe.printStackTrace(System.out);
213*795d594fSAndroid Build Coastguard Worker             }
214*795d594fSAndroid Build Coastguard Worker         }
215*795d594fSAndroid Build Coastguard Worker     }
216*795d594fSAndroid Build Coastguard Worker 
217*795d594fSAndroid Build Coastguard Worker     /**
218*795d594fSAndroid Build Coastguard Worker      * Test a doubled class that extends the base class.
219*795d594fSAndroid Build Coastguard Worker      */
testExtend(ClassLoader loader)220*795d594fSAndroid Build Coastguard Worker     static void testExtend(ClassLoader loader) {
221*795d594fSAndroid Build Coastguard Worker         Class<?> doubledExtendClass;
222*795d594fSAndroid Build Coastguard Worker         Object obj;
223*795d594fSAndroid Build Coastguard Worker 
224*795d594fSAndroid Build Coastguard Worker         /* get the "alternate" version of DoubledExtend */
225*795d594fSAndroid Build Coastguard Worker         try {
226*795d594fSAndroid Build Coastguard Worker             doubledExtendClass = loader.loadClass("DoubledExtend");
227*795d594fSAndroid Build Coastguard Worker             //System.out.println("+++ DoubledExtend is " + doubledExtendClass
228*795d594fSAndroid Build Coastguard Worker             //    + " in " + doubledExtendClass.getClassLoader());
229*795d594fSAndroid Build Coastguard Worker         } catch (ClassNotFoundException cnfe) {
230*795d594fSAndroid Build Coastguard Worker             System.out.println("loadClass failed: " + cnfe);
231*795d594fSAndroid Build Coastguard Worker             return;
232*795d594fSAndroid Build Coastguard Worker         }
233*795d594fSAndroid Build Coastguard Worker 
234*795d594fSAndroid Build Coastguard Worker         /* instantiate */
235*795d594fSAndroid Build Coastguard Worker         try {
236*795d594fSAndroid Build Coastguard Worker             obj = doubledExtendClass.newInstance();
237*795d594fSAndroid Build Coastguard Worker         } catch (InstantiationException ie) {
238*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + ie);
239*795d594fSAndroid Build Coastguard Worker             return;
240*795d594fSAndroid Build Coastguard Worker         } catch (IllegalAccessException iae) {
241*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + iae);
242*795d594fSAndroid Build Coastguard Worker             return;
243*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
244*795d594fSAndroid Build Coastguard Worker             System.out.println("Got expected LinkageError on DE");
245*795d594fSAndroid Build Coastguard Worker             return;
246*795d594fSAndroid Build Coastguard Worker         }
247*795d594fSAndroid Build Coastguard Worker 
248*795d594fSAndroid Build Coastguard Worker         /* use the base class reference to get a CL-specific instance */
249*795d594fSAndroid Build Coastguard Worker         Base baseRef = (Base) obj;
250*795d594fSAndroid Build Coastguard Worker         DoubledExtend de = baseRef.getExtended();
251*795d594fSAndroid Build Coastguard Worker 
252*795d594fSAndroid Build Coastguard Worker         /* try to call through it */
253*795d594fSAndroid Build Coastguard Worker         try {
254*795d594fSAndroid Build Coastguard Worker             String result;
255*795d594fSAndroid Build Coastguard Worker 
256*795d594fSAndroid Build Coastguard Worker             result = Base.doStuff(de);
257*795d594fSAndroid Build Coastguard Worker             System.out.println("ERROR: did not get LinkageError on DE");
258*795d594fSAndroid Build Coastguard Worker             System.out.println("(result=" + result + ")");
259*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
260*795d594fSAndroid Build Coastguard Worker             System.out.println("Got expected LinkageError on DE");
261*795d594fSAndroid Build Coastguard Worker             return;
262*795d594fSAndroid Build Coastguard Worker         }
263*795d594fSAndroid Build Coastguard Worker     }
264*795d594fSAndroid Build Coastguard Worker 
265*795d594fSAndroid Build Coastguard Worker     /**
266*795d594fSAndroid Build Coastguard Worker      * Test a doubled class that extends the base class, but is okay since
267*795d594fSAndroid Build Coastguard Worker      * it doesn't override the base class method.
268*795d594fSAndroid Build Coastguard Worker      */
testExtendOkay(ClassLoader loader)269*795d594fSAndroid Build Coastguard Worker     static void testExtendOkay(ClassLoader loader) {
270*795d594fSAndroid Build Coastguard Worker         Class<?> doubledExtendOkayClass;
271*795d594fSAndroid Build Coastguard Worker         Object obj;
272*795d594fSAndroid Build Coastguard Worker 
273*795d594fSAndroid Build Coastguard Worker         /* get the "alternate" version of DoubledExtendOkay */
274*795d594fSAndroid Build Coastguard Worker         try {
275*795d594fSAndroid Build Coastguard Worker             doubledExtendOkayClass = loader.loadClass("DoubledExtendOkay");
276*795d594fSAndroid Build Coastguard Worker         } catch (ClassNotFoundException cnfe) {
277*795d594fSAndroid Build Coastguard Worker             System.out.println("loadClass failed: " + cnfe);
278*795d594fSAndroid Build Coastguard Worker             return;
279*795d594fSAndroid Build Coastguard Worker         }
280*795d594fSAndroid Build Coastguard Worker 
281*795d594fSAndroid Build Coastguard Worker         /* instantiate */
282*795d594fSAndroid Build Coastguard Worker         try {
283*795d594fSAndroid Build Coastguard Worker             obj = doubledExtendOkayClass.newInstance();
284*795d594fSAndroid Build Coastguard Worker         } catch (InstantiationException ie) {
285*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + ie);
286*795d594fSAndroid Build Coastguard Worker             return;
287*795d594fSAndroid Build Coastguard Worker         } catch (IllegalAccessException iae) {
288*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + iae);
289*795d594fSAndroid Build Coastguard Worker             return;
290*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
291*795d594fSAndroid Build Coastguard Worker             System.out.println("Got unexpected LinkageError on DEO");
292*795d594fSAndroid Build Coastguard Worker             le.printStackTrace(System.out);
293*795d594fSAndroid Build Coastguard Worker             return;
294*795d594fSAndroid Build Coastguard Worker         }
295*795d594fSAndroid Build Coastguard Worker 
296*795d594fSAndroid Build Coastguard Worker         /* use the base class reference to get a CL-specific instance */
297*795d594fSAndroid Build Coastguard Worker         BaseOkay baseRef = (BaseOkay) obj;
298*795d594fSAndroid Build Coastguard Worker         DoubledExtendOkay de = baseRef.getExtended();
299*795d594fSAndroid Build Coastguard Worker 
300*795d594fSAndroid Build Coastguard Worker         /* try to call through it */
301*795d594fSAndroid Build Coastguard Worker         try {
302*795d594fSAndroid Build Coastguard Worker             String result;
303*795d594fSAndroid Build Coastguard Worker 
304*795d594fSAndroid Build Coastguard Worker             result = BaseOkay.doStuff(de);
305*795d594fSAndroid Build Coastguard Worker             System.out.println("Got DEO result " + result);
306*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
307*795d594fSAndroid Build Coastguard Worker             System.out.println("Got unexpected LinkageError on DEO");
308*795d594fSAndroid Build Coastguard Worker             le.printStackTrace(System.out);
309*795d594fSAndroid Build Coastguard Worker             return;
310*795d594fSAndroid Build Coastguard Worker         }
311*795d594fSAndroid Build Coastguard Worker     }
312*795d594fSAndroid Build Coastguard Worker 
313*795d594fSAndroid Build Coastguard Worker     /**
314*795d594fSAndroid Build Coastguard Worker      * Try to access a doubled class through a class that implements
315*795d594fSAndroid Build Coastguard Worker      * an interface declared in a different class.
316*795d594fSAndroid Build Coastguard Worker      */
testInterface(ClassLoader loader)317*795d594fSAndroid Build Coastguard Worker     static void testInterface(ClassLoader loader) {
318*795d594fSAndroid Build Coastguard Worker         Class<?> getDoubledClass;
319*795d594fSAndroid Build Coastguard Worker         Object obj;
320*795d594fSAndroid Build Coastguard Worker 
321*795d594fSAndroid Build Coastguard Worker         /* get GetDoubled from the "alternate" class loader */
322*795d594fSAndroid Build Coastguard Worker         try {
323*795d594fSAndroid Build Coastguard Worker             getDoubledClass = loader.loadClass("GetDoubled");
324*795d594fSAndroid Build Coastguard Worker         } catch (ClassNotFoundException cnfe) {
325*795d594fSAndroid Build Coastguard Worker             System.out.println("loadClass failed: " + cnfe);
326*795d594fSAndroid Build Coastguard Worker             return;
327*795d594fSAndroid Build Coastguard Worker         }
328*795d594fSAndroid Build Coastguard Worker 
329*795d594fSAndroid Build Coastguard Worker         /* instantiate */
330*795d594fSAndroid Build Coastguard Worker         try {
331*795d594fSAndroid Build Coastguard Worker             obj = getDoubledClass.newInstance();
332*795d594fSAndroid Build Coastguard Worker         } catch (InstantiationException ie) {
333*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + ie);
334*795d594fSAndroid Build Coastguard Worker             return;
335*795d594fSAndroid Build Coastguard Worker         } catch (IllegalAccessException iae) {
336*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + iae);
337*795d594fSAndroid Build Coastguard Worker             return;
338*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
339*795d594fSAndroid Build Coastguard Worker             // Dalvik bails here
340*795d594fSAndroid Build Coastguard Worker             System.out.println("Got LinkageError on GD");
341*795d594fSAndroid Build Coastguard Worker             return;
342*795d594fSAndroid Build Coastguard Worker         }
343*795d594fSAndroid Build Coastguard Worker 
344*795d594fSAndroid Build Coastguard Worker         /*
345*795d594fSAndroid Build Coastguard Worker          * Cast the object to the interface, and try to use it.
346*795d594fSAndroid Build Coastguard Worker          */
347*795d594fSAndroid Build Coastguard Worker         IGetDoubled iface = (IGetDoubled) obj;
348*795d594fSAndroid Build Coastguard Worker         try {
349*795d594fSAndroid Build Coastguard Worker             /* "de" will be the wrong variety of DoubledExtendOkay */
350*795d594fSAndroid Build Coastguard Worker             DoubledExtendOkay de = iface.getDoubled();
351*795d594fSAndroid Build Coastguard Worker             // reference impl bails here
352*795d594fSAndroid Build Coastguard Worker             String str = de.getStr();
353*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
354*795d594fSAndroid Build Coastguard Worker             System.out.println("Got LinkageError on GD");
355*795d594fSAndroid Build Coastguard Worker             return;
356*795d594fSAndroid Build Coastguard Worker         }
357*795d594fSAndroid Build Coastguard Worker         System.out.println("Should have failed by now on GetDoubled");
358*795d594fSAndroid Build Coastguard Worker     }
359*795d594fSAndroid Build Coastguard Worker 
360*795d594fSAndroid Build Coastguard Worker     /**
361*795d594fSAndroid Build Coastguard Worker      * Throw an abstract class into the middle and see what happens.
362*795d594fSAndroid Build Coastguard Worker      */
testAbstract(ClassLoader loader)363*795d594fSAndroid Build Coastguard Worker     static void testAbstract(ClassLoader loader) {
364*795d594fSAndroid Build Coastguard Worker         Class<?> abstractGetClass;
365*795d594fSAndroid Build Coastguard Worker         Object obj;
366*795d594fSAndroid Build Coastguard Worker 
367*795d594fSAndroid Build Coastguard Worker         /* get AbstractGet from the "alternate" loader */
368*795d594fSAndroid Build Coastguard Worker         try {
369*795d594fSAndroid Build Coastguard Worker             abstractGetClass = loader.loadClass("AbstractGet");
370*795d594fSAndroid Build Coastguard Worker         } catch (ClassNotFoundException cnfe) {
371*795d594fSAndroid Build Coastguard Worker             System.out.println("loadClass ta failed: " + cnfe);
372*795d594fSAndroid Build Coastguard Worker             return;
373*795d594fSAndroid Build Coastguard Worker         }
374*795d594fSAndroid Build Coastguard Worker 
375*795d594fSAndroid Build Coastguard Worker         /* instantiate */
376*795d594fSAndroid Build Coastguard Worker         try {
377*795d594fSAndroid Build Coastguard Worker             obj = abstractGetClass.newInstance();
378*795d594fSAndroid Build Coastguard Worker         } catch (InstantiationException ie) {
379*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + ie);
380*795d594fSAndroid Build Coastguard Worker             return;
381*795d594fSAndroid Build Coastguard Worker         } catch (IllegalAccessException iae) {
382*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + iae);
383*795d594fSAndroid Build Coastguard Worker             return;
384*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
385*795d594fSAndroid Build Coastguard Worker             System.out.println("Got LinkageError on TA");
386*795d594fSAndroid Build Coastguard Worker             return;
387*795d594fSAndroid Build Coastguard Worker         }
388*795d594fSAndroid Build Coastguard Worker 
389*795d594fSAndroid Build Coastguard Worker         /* use the base class reference to get a CL-specific instance */
390*795d594fSAndroid Build Coastguard Worker         BaseOkay baseRef = (BaseOkay) obj;
391*795d594fSAndroid Build Coastguard Worker         DoubledExtendOkay de = baseRef.getExtended();
392*795d594fSAndroid Build Coastguard Worker 
393*795d594fSAndroid Build Coastguard Worker         /* try to call through it */
394*795d594fSAndroid Build Coastguard Worker         try {
395*795d594fSAndroid Build Coastguard Worker             String result;
396*795d594fSAndroid Build Coastguard Worker 
397*795d594fSAndroid Build Coastguard Worker             result = BaseOkay.doStuff(de);
398*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
399*795d594fSAndroid Build Coastguard Worker             System.out.println("Got LinkageError on TA");
400*795d594fSAndroid Build Coastguard Worker             return;
401*795d594fSAndroid Build Coastguard Worker         }
402*795d594fSAndroid Build Coastguard Worker         System.out.println("Should have failed by now in testAbstract");
403*795d594fSAndroid Build Coastguard Worker     }
404*795d594fSAndroid Build Coastguard Worker 
405*795d594fSAndroid Build Coastguard Worker     /**
406*795d594fSAndroid Build Coastguard Worker      * Test a doubled class that implements a common interface.
407*795d594fSAndroid Build Coastguard Worker      */
testImplement(ClassLoader loader)408*795d594fSAndroid Build Coastguard Worker     static void testImplement(ClassLoader loader) {
409*795d594fSAndroid Build Coastguard Worker         Class<?> doubledImplementClass;
410*795d594fSAndroid Build Coastguard Worker         Object obj;
411*795d594fSAndroid Build Coastguard Worker 
412*795d594fSAndroid Build Coastguard Worker         useImplement(new DoubledImplement(), true);
413*795d594fSAndroid Build Coastguard Worker 
414*795d594fSAndroid Build Coastguard Worker         /* get the "alternate" version of DoubledImplement */
415*795d594fSAndroid Build Coastguard Worker         try {
416*795d594fSAndroid Build Coastguard Worker             doubledImplementClass = loader.loadClass("DoubledImplement");
417*795d594fSAndroid Build Coastguard Worker         } catch (ClassNotFoundException cnfe) {
418*795d594fSAndroid Build Coastguard Worker             System.out.println("loadClass failed: " + cnfe);
419*795d594fSAndroid Build Coastguard Worker             return;
420*795d594fSAndroid Build Coastguard Worker         }
421*795d594fSAndroid Build Coastguard Worker 
422*795d594fSAndroid Build Coastguard Worker         /* instantiate */
423*795d594fSAndroid Build Coastguard Worker         try {
424*795d594fSAndroid Build Coastguard Worker             obj = doubledImplementClass.newInstance();
425*795d594fSAndroid Build Coastguard Worker         } catch (InstantiationException ie) {
426*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + ie);
427*795d594fSAndroid Build Coastguard Worker             return;
428*795d594fSAndroid Build Coastguard Worker         } catch (IllegalAccessException iae) {
429*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + iae);
430*795d594fSAndroid Build Coastguard Worker             return;
431*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
432*795d594fSAndroid Build Coastguard Worker             System.out.println("Got LinkageError on DI (early)");
433*795d594fSAndroid Build Coastguard Worker             return;
434*795d594fSAndroid Build Coastguard Worker         }
435*795d594fSAndroid Build Coastguard Worker 
436*795d594fSAndroid Build Coastguard Worker         /* if we lived this long, try to do something with it */
437*795d594fSAndroid Build Coastguard Worker         ICommon icommon = (ICommon) obj;
438*795d594fSAndroid Build Coastguard Worker         useImplement(icommon.getDoubledInstance(), false);
439*795d594fSAndroid Build Coastguard Worker     }
440*795d594fSAndroid Build Coastguard Worker 
441*795d594fSAndroid Build Coastguard Worker     /**
442*795d594fSAndroid Build Coastguard Worker      * Do something with a DoubledImplement instance.
443*795d594fSAndroid Build Coastguard Worker      */
useImplement(DoubledImplement di, boolean isOne)444*795d594fSAndroid Build Coastguard Worker     static void useImplement(DoubledImplement di, boolean isOne) {
445*795d594fSAndroid Build Coastguard Worker         //System.out.println("useObject: " + di.toString() + " -- "
446*795d594fSAndroid Build Coastguard Worker         //    + di.getClass().getClassLoader());
447*795d594fSAndroid Build Coastguard Worker         try {
448*795d594fSAndroid Build Coastguard Worker             di.one();
449*795d594fSAndroid Build Coastguard Worker             if (!isOne) {
450*795d594fSAndroid Build Coastguard Worker                 System.out.println("ERROR: did not get LinkageError on DI");
451*795d594fSAndroid Build Coastguard Worker             }
452*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
453*795d594fSAndroid Build Coastguard Worker             if (!isOne) {
454*795d594fSAndroid Build Coastguard Worker                 System.out.println("Got LinkageError on DI (late)");
455*795d594fSAndroid Build Coastguard Worker             } else {
456*795d594fSAndroid Build Coastguard Worker                 throw le;
457*795d594fSAndroid Build Coastguard Worker             }
458*795d594fSAndroid Build Coastguard Worker         }
459*795d594fSAndroid Build Coastguard Worker     }
460*795d594fSAndroid Build Coastguard Worker 
461*795d594fSAndroid Build Coastguard Worker 
462*795d594fSAndroid Build Coastguard Worker     /**
463*795d594fSAndroid Build Coastguard Worker      * Test a class that implements an interface with a super-interface
464*795d594fSAndroid Build Coastguard Worker      * that refers to a doubled class.
465*795d594fSAndroid Build Coastguard Worker      */
testIfaceImplement(ClassLoader loader)466*795d594fSAndroid Build Coastguard Worker     static void testIfaceImplement(ClassLoader loader) {
467*795d594fSAndroid Build Coastguard Worker         Class<?> ifaceImplClass;
468*795d594fSAndroid Build Coastguard Worker         Object obj;
469*795d594fSAndroid Build Coastguard Worker 
470*795d594fSAndroid Build Coastguard Worker         /*
471*795d594fSAndroid Build Coastguard Worker          * Create an instance of IfaceImpl.  We also pull in
472*795d594fSAndroid Build Coastguard Worker          * DoubledImplement2 from the other class loader; without this
473*795d594fSAndroid Build Coastguard Worker          * we don't fail in some implementations.
474*795d594fSAndroid Build Coastguard Worker          */
475*795d594fSAndroid Build Coastguard Worker         try {
476*795d594fSAndroid Build Coastguard Worker             ifaceImplClass = loader.loadClass("IfaceImpl");
477*795d594fSAndroid Build Coastguard Worker             ifaceImplClass = loader.loadClass("DoubledImplement2");
478*795d594fSAndroid Build Coastguard Worker         } catch (ClassNotFoundException cnfe) {
479*795d594fSAndroid Build Coastguard Worker             System.out.println("loadClass failed: " + cnfe);
480*795d594fSAndroid Build Coastguard Worker             return;
481*795d594fSAndroid Build Coastguard Worker         }
482*795d594fSAndroid Build Coastguard Worker 
483*795d594fSAndroid Build Coastguard Worker         /* instantiate */
484*795d594fSAndroid Build Coastguard Worker         try {
485*795d594fSAndroid Build Coastguard Worker             obj = ifaceImplClass.newInstance();
486*795d594fSAndroid Build Coastguard Worker         } catch (InstantiationException ie) {
487*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + ie);
488*795d594fSAndroid Build Coastguard Worker             return;
489*795d594fSAndroid Build Coastguard Worker         } catch (IllegalAccessException iae) {
490*795d594fSAndroid Build Coastguard Worker             System.out.println("newInstance failed: " + iae);
491*795d594fSAndroid Build Coastguard Worker             return;
492*795d594fSAndroid Build Coastguard Worker         } catch (LinkageError le) {
493*795d594fSAndroid Build Coastguard Worker             System.out.println("Got LinkageError on IDI (early)");
494*795d594fSAndroid Build Coastguard Worker             //System.out.println(le);
495*795d594fSAndroid Build Coastguard Worker             return;
496*795d594fSAndroid Build Coastguard Worker         }
497*795d594fSAndroid Build Coastguard Worker 
498*795d594fSAndroid Build Coastguard Worker         /*
499*795d594fSAndroid Build Coastguard Worker          * Without the pre-load of FancyLoader->DoubledImplement2, some
500*795d594fSAndroid Build Coastguard Worker          * implementations will happily execute through this part.  "obj"
501*795d594fSAndroid Build Coastguard Worker          * comes from FancyLoader, but the di2 returned from ifaceSuper
502*795d594fSAndroid Build Coastguard Worker          * comes from the application class loader.
503*795d594fSAndroid Build Coastguard Worker          */
504*795d594fSAndroid Build Coastguard Worker         IfaceSuper ifaceSuper = (IfaceSuper) obj;
505*795d594fSAndroid Build Coastguard Worker         DoubledImplement2 di2 = ifaceSuper.getDoubledInstance2();
506*795d594fSAndroid Build Coastguard Worker         di2.one();
507*795d594fSAndroid Build Coastguard Worker     }
508*795d594fSAndroid Build Coastguard Worker 
testClassForName()509*795d594fSAndroid Build Coastguard Worker     static void testClassForName() throws Exception {
510*795d594fSAndroid Build Coastguard Worker         System.out.println(Class.forName("Main").toString());
511*795d594fSAndroid Build Coastguard Worker         try {
512*795d594fSAndroid Build Coastguard Worker             System.out.println(Class.forName("Main", false, null).toString());
513*795d594fSAndroid Build Coastguard Worker         } catch (ClassNotFoundException expected) {
514*795d594fSAndroid Build Coastguard Worker             System.out.println("Got expected ClassNotFoundException");
515*795d594fSAndroid Build Coastguard Worker         }
516*795d594fSAndroid Build Coastguard Worker     }
517*795d594fSAndroid Build Coastguard Worker }
518