Main.java revision cab8be0c6e1e9a683402d5a71b037723a6b15bb2
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/** 18 * Class loader test. 19 */ 20public class Main { 21 /** 22 * Main entry point. 23 */ 24 public static void main(String[] args) { 25 FancyLoader loader; 26 27 loader = new FancyLoader(ClassLoader.getSystemClassLoader()); 28 29 /* 30 * This statement has no effect on this program, but it can 31 * change the point where a LinkageException is thrown in 32 * testImplement(). When this is present the "reference 33 * implementation" throws an exception from Class.newInstance(), 34 * when it's absent the exception is deferred until the first time 35 * we call a method that isn't actually implemented. 36 * 37 * This isn't the class that fails -- it's a class with the same 38 * name in the "fancy" class loader -- but the VM thinks it has a 39 * reference to one of these; presumably the difference is that 40 * without this the VM finds itself holding a reference to an 41 * instance of an uninitialized class. 42 */ 43 System.out.println("base: " + DoubledImplement.class); 44 System.out.println("base2: " + DoubledImplement2.class); 45 46 /* 47 * Run tests. 48 */ 49 testAccess1(loader); 50 testAccess2(loader); 51 testAccess3(loader); 52 53 testExtend(loader); 54 testExtendOkay(loader); 55 testImplement(loader); 56 testIfaceImplement(loader); 57 } 58 59 /** 60 * See if we can load a class that isn't public to us. We should be 61 * able to load it but not instantiate it. 62 */ 63 static void testAccess1(ClassLoader loader) { 64 Class altClass; 65 66 try { 67 altClass = loader.loadClass("Inaccessible1"); 68 } catch (ClassNotFoundException cnfe) { 69 System.err.println("loadClass failed"); 70 cnfe.printStackTrace(); 71 return; 72 } 73 74 /* instantiate */ 75 Object obj; 76 try { 77 obj = altClass.newInstance(); 78 System.err.println("ERROR: Inaccessible1 was accessible"); 79 } catch (InstantiationException ie) { 80 System.err.println("newInstance failed: " + ie); 81 return; 82 } catch (IllegalAccessException iae) { 83 System.out.println("Got expected access exception #1"); 84 //System.out.println("+++ " + iae); 85 return; 86 } 87 } 88 89 /** 90 * See if we can load a class whose base class is not accessible to it 91 * (though the base *is* accessible to us). 92 */ 93 static void testAccess2(ClassLoader loader) { 94 Class altClass; 95 96 try { 97 altClass = loader.loadClass("Inaccessible2"); 98 System.err.println("ERROR: Inaccessible2 was accessible"); 99 } catch (ClassNotFoundException cnfe) { 100 Throwable cause = cnfe.getCause(); 101 if (cause instanceof IllegalAccessError) { 102 System.out.println("Got expected CNFE/IAE #2"); 103 } else { 104 System.err.println("Got unexpected CNFE/IAE #2"); 105 cnfe.printStackTrace(); 106 } 107 } 108 } 109 110 /** 111 * See if we can load a class with an inaccessible interface. 112 */ 113 static void testAccess3(ClassLoader loader) { 114 Class altClass; 115 116 try { 117 altClass = loader.loadClass("Inaccessible3"); 118 System.err.println("ERROR: Inaccessible3 was accessible"); 119 } catch (ClassNotFoundException cnfe) { 120 Throwable cause = cnfe.getCause(); 121 if (cause instanceof IllegalAccessError) { 122 System.out.println("Got expected CNFE/IAE #3"); 123 } else { 124 System.err.println("Got unexpected CNFE/IAE #3"); 125 cnfe.printStackTrace(); 126 } 127 } 128 } 129 130 /** 131 * Test a doubled class that extends the base class. 132 */ 133 static void testExtend(ClassLoader loader) { 134 Class doubledExtendClass; 135 Object obj; 136 137 /* get the "alternate" version of DoubledExtend */ 138 try { 139 doubledExtendClass = loader.loadClass("DoubledExtend"); 140 //System.out.println("+++ DoubledExtend is " + doubledExtendClass 141 // + " in " + doubledExtendClass.getClassLoader()); 142 } catch (ClassNotFoundException cnfe) { 143 System.err.println("loadClass failed: " + cnfe); 144 return; 145 } 146 147 /* instantiate */ 148 try { 149 obj = doubledExtendClass.newInstance(); 150 } catch (InstantiationException ie) { 151 System.err.println("newInstance failed: " + ie); 152 return; 153 } catch (IllegalAccessException iae) { 154 System.err.println("newInstance failed: " + iae); 155 return; 156 } catch (LinkageError le) { 157 System.out.println("Got expected LinkageError on DE"); 158 return; 159 } 160 161 /* use the base class reference to get a CL-specific instance */ 162 Base baseRef = (Base) obj; 163 DoubledExtend de = baseRef.getExtended(); 164 165 /* try to call through it */ 166 try { 167 String result; 168 169 result = Base.doStuff(de); 170 System.err.println("ERROR: did not get LinkageError on DE"); 171 System.err.println("(result=" + result + ")"); 172 } catch (LinkageError le) { 173 System.out.println("Got expected LinkageError on DE"); 174 return; 175 } 176 } 177 178 /** 179 * Test a doubled class that extends the base class, but is okay since 180 * it doesn't override the base class method. 181 */ 182 static void testExtendOkay(ClassLoader loader) { 183 Class doubledExtendOkayClass; 184 Object obj; 185 186 /* get the "alternate" version of DoubledExtendOkay */ 187 try { 188 doubledExtendOkayClass = loader.loadClass("DoubledExtendOkay"); 189 } catch (ClassNotFoundException cnfe) { 190 System.err.println("loadClass failed: " + cnfe); 191 return; 192 } 193 194 /* instantiate */ 195 try { 196 obj = doubledExtendOkayClass.newInstance(); 197 } catch (InstantiationException ie) { 198 System.err.println("newInstance failed: " + ie); 199 return; 200 } catch (IllegalAccessException iae) { 201 System.err.println("newInstance failed: " + iae); 202 return; 203 } catch (LinkageError le) { 204 System.err.println("Got unexpected LinkageError on DEO"); 205 le.printStackTrace(); 206 return; 207 } 208 209 /* use the base class reference to get a CL-specific instance */ 210 BaseOkay baseRef = (BaseOkay) obj; 211 DoubledExtendOkay de = baseRef.getExtended(); 212 213 /* try to call through it */ 214 try { 215 String result; 216 217 result = BaseOkay.doStuff(de); 218 System.out.println("Got DEO result " + result); 219 } catch (LinkageError le) { 220 System.err.println("Got unexpected LinkageError on DEO"); 221 le.printStackTrace(); 222 return; 223 } 224 } 225 226 /** 227 * Test a doubled class that implements a common interface. 228 */ 229 static void testImplement(ClassLoader loader) { 230 Class doubledImplementClass; 231 Object obj; 232 233 useImplement(new DoubledImplement(), true); 234 235 /* get the "alternate" version of DoubledImplement */ 236 try { 237 doubledImplementClass = loader.loadClass("DoubledImplement"); 238 } catch (ClassNotFoundException cnfe) { 239 System.err.println("loadClass failed: " + cnfe); 240 return; 241 } 242 243 /* instantiate */ 244 try { 245 obj = doubledImplementClass.newInstance(); 246 } catch (InstantiationException ie) { 247 System.err.println("newInstance failed: " + ie); 248 return; 249 } catch (IllegalAccessException iae) { 250 System.err.println("newInstance failed: " + iae); 251 return; 252 } catch (LinkageError le) { 253 System.out.println("Got LinkageError on DI (early)"); 254 return; 255 } 256 257 /* if we lived this long, try to do something with it */ 258 ICommon icommon = (ICommon) obj; 259 useImplement(icommon.getDoubledInstance(), false); 260 } 261 262 /** 263 * Do something with a DoubledImplement instance. 264 */ 265 static void useImplement(DoubledImplement di, boolean isOne) { 266 //System.out.println("useObject: " + di.toString() + " -- " 267 // + di.getClass().getClassLoader()); 268 try { 269 di.one(); 270 if (!isOne) { 271 System.err.println("ERROR: did not get LinkageError on DI"); 272 } 273 } catch (LinkageError le) { 274 if (!isOne) { 275 System.out.println("Got LinkageError on DI (late)"); 276 } else { 277 throw le; 278 } 279 } 280 } 281 282 283 /** 284 * Test a class that implements an interface with a super-interface 285 * that refers to a doubled class. 286 */ 287 static void testIfaceImplement(ClassLoader loader) { 288 Class ifaceImplClass; 289 Object obj; 290 291 /* 292 * Create an instance of IfaceImpl. We also pull in 293 * DoubledImplement2 from the other class loader; without this 294 * we don't fail in some implementations. 295 */ 296 try { 297 ifaceImplClass = loader.loadClass("IfaceImpl"); 298 ifaceImplClass = loader.loadClass("DoubledImplement2"); 299 } catch (ClassNotFoundException cnfe) { 300 System.err.println("loadClass failed: " + cnfe); 301 return; 302 } 303 304 /* instantiate */ 305 try { 306 obj = ifaceImplClass.newInstance(); 307 } catch (InstantiationException ie) { 308 System.err.println("newInstance failed: " + ie); 309 return; 310 } catch (IllegalAccessException iae) { 311 System.err.println("newInstance failed: " + iae); 312 return; 313 } catch (LinkageError le) { 314 System.out.println("Got LinkageError on IDI (early)"); 315 //System.out.println(le); 316 return; 317 } 318 319 /* 320 * Without the pre-load of FancyLoader->DoubledImplement2, some 321 * implementations will happily execute through this part. "obj" 322 * comes from FancyLoader, but the di2 returned from ifaceSuper 323 * comes from the application class loader. 324 */ 325 IfaceSuper ifaceSuper = (IfaceSuper) obj; 326 DoubledImplement2 di2 = ifaceSuper.getDoubledInstance2(); 327 di2.one(); 328 } 329} 330 331