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