Main.java revision 89c1feb0a69a7707b271086e749975b3f7acacf7
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 testImplement(loader); 55 testIfaceImplement(loader); 56 } 57 58 /** 59 * See if we can load a class that isn't public to us. We should be 60 * able to load it but not instantiate it. 61 */ 62 static void testAccess1(ClassLoader loader) { 63 Class altClass; 64 65 try { 66 altClass = loader.loadClass("Inaccessible1"); 67 } catch (ClassNotFoundException cnfe) { 68 System.err.println("loadClass failed"); 69 cnfe.printStackTrace(); 70 return; 71 } 72 73 /* instantiate */ 74 Object obj; 75 try { 76 obj = altClass.newInstance(); 77 System.err.println("ERROR: Inaccessible1 was accessible"); 78 } catch (InstantiationException ie) { 79 System.err.println("newInstance failed: " + ie); 80 return; 81 } catch (IllegalAccessException iae) { 82 System.out.println("Got expected access exception #1"); 83 //System.out.println("+++ " + iae); 84 return; 85 } 86 } 87 88 /** 89 * See if we can load a class whose base class is not accessible to it 90 * (though the base *is* accessible to us). 91 */ 92 static void testAccess2(ClassLoader loader) { 93 Class altClass; 94 95 try { 96 altClass = loader.loadClass("Inaccessible2"); 97 System.err.println("ERROR: Inaccessible2 was accessible"); 98 } catch (ClassNotFoundException cnfe) { 99 Throwable cause = cnfe.getCause(); 100 if (cause instanceof IllegalAccessError) { 101 System.out.println("Got expected CNFE/IAE #2"); 102 } else { 103 System.err.println("Got unexpected CNFE/IAE #2"); 104 cnfe.printStackTrace(); 105 } 106 } 107 } 108 109 /** 110 * See if we can load a class with an inaccessible interface. 111 */ 112 static void testAccess3(ClassLoader loader) { 113 Class altClass; 114 115 try { 116 altClass = loader.loadClass("Inaccessible3"); 117 System.err.println("ERROR: Inaccessible3 was accessible"); 118 } catch (ClassNotFoundException cnfe) { 119 Throwable cause = cnfe.getCause(); 120 if (cause instanceof IllegalAccessError) { 121 System.out.println("Got expected CNFE/IAE #3"); 122 } else { 123 System.err.println("Got unexpected CNFE/IAE #3"); 124 cnfe.printStackTrace(); 125 } 126 } 127 } 128 129 /** 130 * Test a doubled class that extends the base class. 131 */ 132 static void testExtend(ClassLoader loader) { 133 Class doubledExtendClass; 134 Object obj; 135 136 /* get the "alternate" version of DoubledExtend */ 137 try { 138 doubledExtendClass = loader.loadClass("DoubledExtend"); 139 //System.out.println("+++ DoubledExtend is " + doubledExtendClass 140 // + " in " + doubledExtendClass.getClassLoader()); 141 } catch (ClassNotFoundException cnfe) { 142 System.err.println("loadClass failed: " + cnfe); 143 return; 144 } 145 146 /* instantiate */ 147 try { 148 obj = doubledExtendClass.newInstance(); 149 } catch (InstantiationException ie) { 150 System.err.println("newInstance failed: " + ie); 151 return; 152 } catch (IllegalAccessException iae) { 153 System.err.println("newInstance failed: " + iae); 154 return; 155 } catch (LinkageError le) { 156 System.out.println("Got expected LinkageError on DE"); 157 return; 158 } 159 160 /* use the base class reference to get a CL-specific instance */ 161 Base baseRef = (Base) obj; 162 DoubledExtend de = baseRef.getExtended(); 163 164 /* try to call through it */ 165 try { 166 String result; 167 168 result = Base.doStuff(de); 169 System.err.println("ERROR: did not get LinkageError on DE"); 170 System.err.println("(result=" + result + ")"); 171 } catch (LinkageError le) { 172 System.out.println("Got expected LinkageError on DE"); 173 return; 174 } 175 } 176 177 /** 178 * Test a doubled class that implements a common interface. 179 */ 180 static void testImplement(ClassLoader loader) { 181 Class doubledImplementClass; 182 Object obj; 183 184 useImplement(new DoubledImplement(), true); 185 186 /* get the "alternate" version of DoubledImplement */ 187 try { 188 doubledImplementClass = loader.loadClass("DoubledImplement"); 189 } catch (ClassNotFoundException cnfe) { 190 System.err.println("loadClass failed: " + cnfe); 191 return; 192 } 193 194 /* instantiate */ 195 try { 196 obj = doubledImplementClass.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.out.println("Got LinkageError on DI (early)"); 205 return; 206 } 207 208 /* if we lived this long, try to do something with it */ 209 ICommon icommon = (ICommon) obj; 210 useImplement(icommon.getDoubledInstance(), false); 211 } 212 213 /** 214 * Do something with a DoubledImplement instance. 215 */ 216 static void useImplement(DoubledImplement di, boolean isOne) { 217 //System.out.println("useObject: " + di.toString() + " -- " 218 // + di.getClass().getClassLoader()); 219 try { 220 di.one(); 221 if (!isOne) { 222 System.err.println("ERROR: did not get LinkageError on DI"); 223 } 224 } catch (LinkageError le) { 225 if (!isOne) { 226 System.out.println("Got LinkageError on DI (late)"); 227 } else { 228 throw le; 229 } 230 } 231 } 232 233 234 /** 235 * Test a class that implements an interface with a super-interface 236 * that refers to a doubled class. 237 */ 238 static void testIfaceImplement(ClassLoader loader) { 239 Class ifaceImplClass; 240 Object obj; 241 242 /* 243 * Create an instance of IfaceImpl. We also pull in 244 * DoubledImplement2 from the other class loader; without this 245 * we don't fail in some implementations. 246 */ 247 try { 248 ifaceImplClass = loader.loadClass("IfaceImpl"); 249 ifaceImplClass = loader.loadClass("DoubledImplement2"); 250 } catch (ClassNotFoundException cnfe) { 251 System.err.println("loadClass failed: " + cnfe); 252 return; 253 } 254 255 /* instantiate */ 256 try { 257 obj = ifaceImplClass.newInstance(); 258 } catch (InstantiationException ie) { 259 System.err.println("newInstance failed: " + ie); 260 return; 261 } catch (IllegalAccessException iae) { 262 System.err.println("newInstance failed: " + iae); 263 return; 264 } catch (LinkageError le) { 265 System.out.println("Got LinkageError on IDI (early)"); 266 //System.out.println(le); 267 return; 268 } 269 270 /* 271 * Without the pre-load of FancyLoader->DoubledImplement2, some 272 * implementations will happily execute through this part. "obj" 273 * comes from FancyLoader, but the di2 returned from ifaceSuper 274 * comes from the application class loader. 275 */ 276 IfaceSuper ifaceSuper = (IfaceSuper) obj; 277 DoubledImplement2 di2 = ifaceSuper.getDoubledInstance2(); 278 di2.one(); 279 } 280} 281 282