1 // Copyright 2006 The Android Open Source Project 2 3 import java.lang.reflect.*; 4 import java.io.IOException; 5 import java.util.Collections; 6 import java.util.ArrayList; 7 import java.util.List; 8 import java.util.Map; 9 10 /** 11 * Reflection test. 12 */ 13 public class Main { 14 private static boolean FULL_ACCESS_CHECKS = false; // b/5861201 15 public Main() {} 16 public Main(ArrayList<Integer> stuff) {} 17 18 void printMethodInfo(Method meth) { 19 Class[] params, exceptions; 20 int i; 21 22 System.out.println("Method name is " + meth.getName()); 23 System.out.println(" Declaring class is " 24 + meth.getDeclaringClass().getName()); 25 params = meth.getParameterTypes(); 26 for (i = 0; i < params.length; i++) 27 System.out.println(" Arg " + i + ": " + params[i].getName()); 28 exceptions = meth.getExceptionTypes(); 29 for (i = 0; i < exceptions.length; i++) 30 System.out.println(" Exc " + i + ": " + exceptions[i].getName()); 31 System.out.println(" Return type is " + meth.getReturnType().getName()); 32 System.out.println(" Access flags are 0x" 33 + Integer.toHexString(meth.getModifiers())); 34 //System.out.println(" GenericStr is " + meth.toGenericString()); 35 } 36 37 void printFieldInfo(Field field) { 38 System.out.println("Field name is " + field.getName()); 39 System.out.println(" Declaring class is " 40 + field.getDeclaringClass().getName()); 41 System.out.println(" Field type is " + field.getType().getName()); 42 System.out.println(" Access flags are 0x" 43 + Integer.toHexString(field.getModifiers())); 44 } 45 46 private void showStrings(Target instance) 47 throws NoSuchFieldException, IllegalAccessException { 48 49 Class target = Target.class; 50 String one, two, three, four; 51 Field field = null; 52 53 field = target.getField("string1"); 54 one = (String) field.get(instance); 55 56 field = target.getField("string2"); 57 two = (String) field.get(instance); 58 59 field = target.getField("string3"); 60 three = (String) field.get(instance); 61 62 System.out.println(" ::: " + one + ":" + two + ":" + three); 63 } 64 65 public static void checkAccess() { 66 try { 67 Class target = otherpackage.Other.class; 68 Object instance = new otherpackage.Other(); 69 Method meth; 70 71 meth = target.getMethod("publicMethod", (Class[]) null); 72 meth.invoke(instance); 73 74 try { 75 meth = target.getMethod("packageMethod", (Class[]) null); 76 System.err.println("succeeded on package-scope method"); 77 } catch (NoSuchMethodException nsme) { 78 // good 79 } 80 81 82 instance = otherpackage.Other.getInnerClassInstance(); 83 target = instance.getClass(); 84 meth = target.getMethod("innerMethod", (Class[]) null); 85 try { 86 if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); } 87 meth.invoke(instance); 88 System.err.println("inner-method invoke unexpectedly worked"); 89 } catch (IllegalAccessException iae) { 90 // good 91 } 92 93 Field field = target.getField("innerField"); 94 try { 95 int x = field.getInt(instance); 96 if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); } 97 System.err.println("field get unexpectedly worked: " + x); 98 } catch (IllegalAccessException iae) { 99 // good 100 } 101 } catch (Exception ex) { 102 System.out.println("----- unexpected exception -----"); 103 ex.printStackTrace(); 104 } 105 } 106 107 public void run() { 108 Class target = Target.class; 109 Method meth = null; 110 Field field = null; 111 boolean excep; 112 113 try { 114 meth = target.getMethod("myMethod", new Class[] { int.class }); 115 116 if (meth.getDeclaringClass() != target) 117 throw new RuntimeException(); 118 printMethodInfo(meth); 119 120 meth = target.getMethod("myMethod", new Class[] { float.class }); 121 printMethodInfo(meth); 122 123 meth = target.getMethod("myNoargMethod", (Class[]) null); 124 printMethodInfo(meth); 125 126 meth = target.getMethod("myMethod", 127 new Class[] { String[].class, float.class, char.class }); 128 printMethodInfo(meth); 129 130 Target instance = new Target(); 131 Object[] argList = new Object[] { 132 new String[] { "hi there" }, 133 new Float(3.1415926f), 134 new Character('Q') 135 }; 136 System.out.println("Before, float is " 137 + ((Float)argList[1]).floatValue()); 138 139 Integer boxval; 140 boxval = (Integer) meth.invoke(instance, argList); 141 System.out.println("Result of invoke: " + boxval.intValue()); 142 143 System.out.println("Calling no-arg void-return method"); 144 meth = target.getMethod("myNoargMethod", (Class[]) null); 145 meth.invoke(instance, (Object[]) null); 146 147 /* try invoking a method that throws an exception */ 148 meth = target.getMethod("throwingMethod", (Class[]) null); 149 try { 150 meth.invoke(instance, (Object[]) null); 151 System.out.println("GLITCH: didn't throw"); 152 } catch (InvocationTargetException ite) { 153 System.out.println("Invoke got expected exception:"); 154 System.out.println(ite.getClass().getName()); 155 System.out.println(ite.getCause()); 156 } 157 catch (Exception ex) { 158 System.out.println("GLITCH: invoke got wrong exception:"); 159 ex.printStackTrace(); 160 } 161 System.out.println(""); 162 163 164 field = target.getField("string1"); 165 if (field.getDeclaringClass() != target) 166 throw new RuntimeException(); 167 printFieldInfo(field); 168 String strVal = (String) field.get(instance); 169 System.out.println(" string1 value is '" + strVal + "'"); 170 171 showStrings(instance); 172 173 field.set(instance, new String("a new string")); 174 strVal = (String) field.get(instance); 175 System.out.println(" string1 value is now '" + strVal + "'"); 176 177 showStrings(instance); 178 179 try { 180 field.set(instance, new Object()); 181 System.out.println("WARNING: able to store Object into String"); 182 } 183 catch (IllegalArgumentException iae) { 184 System.out.println(" got expected illegal obj store exc"); 185 } 186 187 188 try { 189 String four; 190 field = target.getField("string4"); 191 four = (String) field.get(instance); 192 System.out.println("WARNING: able to access string4: " 193 + four); 194 } 195 catch (IllegalAccessException iae) { 196 System.out.println(" got expected access exc"); 197 } 198 catch (NoSuchFieldException nsfe) { 199 System.out.println(" got the other expected access exc"); 200 } 201 try { 202 String three; 203 field = target.getField("string3"); 204 three = (String) field.get(this); 205 System.out.println("WARNING: able to get string3 in wrong obj: " 206 + three); 207 } 208 catch (IllegalArgumentException iae) { 209 System.out.println(" got expected arg exc"); 210 } 211 212 /* 213 * Try setting a field to null. 214 */ 215 String four; 216 field = target.getDeclaredField("string3"); 217 field.set(instance, null); 218 219 /* 220 * Do some stuff with long. 221 */ 222 long longVal; 223 field = target.getField("pubLong"); 224 longVal = field.getLong(instance); 225 System.out.println("pubLong initial value is " + 226 Long.toHexString(longVal)); 227 field.setLong(instance, 0x9988776655443322L); 228 longVal = field.getLong(instance); 229 System.out.println("pubLong new value is " + 230 Long.toHexString(longVal)); 231 232 233 field = target.getField("superInt"); 234 if (field.getDeclaringClass() == target) 235 throw new RuntimeException(); 236 printFieldInfo(field); 237 int intVal = field.getInt(instance); 238 System.out.println(" superInt value is " + intVal); 239 Integer boxedIntVal = (Integer) field.get(instance); 240 System.out.println(" superInt boxed is " + boxedIntVal); 241 242 field.set(instance, new Integer(20202)); 243 intVal = field.getInt(instance); 244 System.out.println(" superInt value is now " + intVal); 245 field.setShort(instance, (short)30303); 246 intVal = field.getInt(instance); 247 System.out.println(" superInt value (from short) is now " +intVal); 248 field.setInt(instance, 40404); 249 intVal = field.getInt(instance); 250 System.out.println(" superInt value is now " + intVal); 251 try { 252 field.set(instance, new Long(123)); 253 System.out.println("FAIL: expected exception not thrown"); 254 } 255 catch (IllegalArgumentException iae) { 256 System.out.println(" got expected long->int failure"); 257 } 258 try { 259 field.setLong(instance, 123); 260 System.out.println("FAIL: expected exception not thrown"); 261 } 262 catch (IllegalArgumentException iae) { 263 System.out.println(" got expected long->int failure"); 264 } 265 try { 266 field.set(instance, new String("abc")); 267 System.out.println("FAIL: expected exception not thrown"); 268 } 269 catch (IllegalArgumentException iae) { 270 System.out.println(" got expected string->int failure"); 271 } 272 273 try { 274 field.getShort(instance); 275 System.out.println("FAIL: expected exception not thrown"); 276 } 277 catch (IllegalArgumentException iae) { 278 System.out.println(" got expected int->short failure"); 279 } 280 281 field = target.getField("superClassInt"); 282 printFieldInfo(field); 283 int superClassIntVal = field.getInt(instance); 284 System.out.println(" superClassInt value is " + superClassIntVal); 285 286 field = target.getField("staticDouble"); 287 printFieldInfo(field); 288 double staticDoubleVal = field.getDouble(null); 289 System.out.println(" staticDoubleVal value is " + staticDoubleVal); 290 291 try { 292 field.getLong(instance); 293 System.out.println("FAIL: expected exception not thrown"); 294 } 295 catch (IllegalArgumentException iae) { 296 System.out.println(" got expected double->long failure"); 297 } 298 299 excep = false; 300 try { 301 field = target.getField("aPrivateInt"); 302 printFieldInfo(field); 303 } 304 catch (NoSuchFieldException nsfe) { 305 System.out.println("as expected: aPrivateInt not found"); 306 excep = true; 307 } 308 if (!excep) 309 System.out.println("BUG: got aPrivateInt"); 310 311 312 field = target.getField("constantString"); 313 printFieldInfo(field); 314 String val = (String) field.get(instance); 315 System.out.println(" Constant test value is " + val); 316 317 318 field = target.getField("cantTouchThis"); 319 printFieldInfo(field); 320 intVal = field.getInt(instance); 321 System.out.println(" cantTouchThis is " + intVal); 322 try { 323 field.setInt(instance, 99); 324 System.out.println("ERROR: set-final succeeded"); 325 } catch (IllegalAccessException iae) { 326 System.out.println(" got expected set-final failure"); 327 } 328 intVal = field.getInt(instance); 329 System.out.println(" cantTouchThis is now " + intVal); 330 331 field.setAccessible(true); 332 field.setInt(instance, 87); // exercise int version 333 field.set(instance, 88); // exercise Object version 334 intVal = field.getInt(instance); 335 System.out.println(" cantTouchThis is now " + intVal); 336 337 Constructor<Target> cons; 338 Target targ; 339 Object[] args; 340 341 cons = target.getConstructor(new Class[] { int.class,float.class }); 342 args = new Object[] { new Integer(7), new Float(3.3333) }; 343 System.out.println("cons modifiers=" + cons.getModifiers()); 344 targ = cons.newInstance(args); 345 targ.myMethod(17); 346 347 } catch (Exception ex) { 348 System.out.println("----- unexpected exception -----"); 349 ex.printStackTrace(); 350 } 351 352 System.out.println("ReflectTest done!"); 353 } 354 355 public static void checkType() { 356 Method m; 357 358 try { 359 m = Collections.class.getDeclaredMethod("checkType", 360 Object.class, Class.class); 361 } catch (NoSuchMethodException nsme) { 362 nsme.printStackTrace(); 363 return; 364 } 365 366 m.setAccessible(true); 367 try { 368 m.invoke(null, new Object(), Object.class); 369 } catch (IllegalAccessException iae) { 370 iae.printStackTrace(); 371 return; 372 } catch (InvocationTargetException ite) { 373 ite.printStackTrace(); 374 return; 375 } 376 377 try { 378 System.out.println("checkType invoking null"); 379 m.invoke(null, new Object(), int.class); 380 System.out.println("ERROR: should throw InvocationTargetException"); 381 } catch (InvocationTargetException ite) { 382 System.out.println("checkType got expected exception"); 383 } catch (IllegalAccessException iae) { 384 iae.printStackTrace(); 385 return; 386 } 387 } 388 389 public static void checkInit() { 390 Class niuClass = NoisyInitUser.class; 391 Method[] methods; 392 393 methods = niuClass.getDeclaredMethods(); 394 System.out.println("got methods"); 395 /* neither NoisyInit nor NoisyInitUser should be initialized yet */ 396 NoisyInitUser niu = new NoisyInitUser(); 397 NoisyInit ni = new NoisyInit(); 398 399 System.out.println(""); 400 } 401 402 403 /* 404 * Test some generic type stuff. 405 */ 406 public List<String> dummy; 407 public Map<Integer,String> fancyMethod(ArrayList<String> blah) { return null; } 408 public static void checkGeneric() { 409 Field field; 410 try { 411 field = Main.class.getField("dummy"); 412 } catch (NoSuchFieldException nsfe) { 413 throw new RuntimeException(nsfe); 414 } 415 Type listType = field.getGenericType(); 416 System.out.println("generic field: " + listType); 417 418 Method method; 419 try { 420 method = Main.class.getMethod("fancyMethod", 421 new Class[] { ArrayList.class }); 422 } catch (NoSuchMethodException nsme) { 423 throw new RuntimeException(nsme); 424 } 425 Type[] parmTypes = method.getGenericParameterTypes(); 426 Type ret = method.getGenericReturnType(); 427 System.out.println("generic method " + method.getName() + " params='" 428 + stringifyTypeArray(parmTypes) + "' ret='" + ret + "'"); 429 430 Constructor ctor; 431 try { 432 ctor = Main.class.getConstructor(new Class[] { ArrayList.class }); 433 } catch (NoSuchMethodException nsme) { 434 throw new RuntimeException(nsme); 435 } 436 parmTypes = ctor.getGenericParameterTypes(); 437 System.out.println("generic ctor " + ctor.getName() + " params='" 438 + stringifyTypeArray(parmTypes) + "'"); 439 } 440 441 /* 442 * Convert an array of Type into a string. Start with an array count. 443 */ 444 private static String stringifyTypeArray(Type[] types) { 445 StringBuilder stb = new StringBuilder(); 446 boolean first = true; 447 448 stb.append("[" + types.length + "]"); 449 450 for (Type t: types) { 451 if (first) { 452 stb.append(" "); 453 first = false; 454 } else { 455 stb.append(", "); 456 } 457 stb.append(t.toString()); 458 } 459 460 return stb.toString(); 461 } 462 463 464 public static void main(String[] args) { 465 Main test = new Main(); 466 test.run(); 467 468 checkAccess(); 469 checkType(); 470 checkInit(); 471 checkGeneric(); 472 } 473 } 474 475 476 class SuperTarget { 477 public SuperTarget() { 478 System.out.println("SuperTarget constructor ()V"); 479 superInt = 1010101; 480 superClassInt = 1010102; 481 } 482 483 public int myMethod(float floatArg) { 484 System.out.println("myMethod (F)I " + floatArg); 485 return 6; 486 } 487 488 public int superInt; 489 public static int superClassInt; 490 } 491 492 class Target extends SuperTarget { 493 public Target() { 494 System.out.println("Target constructor ()V"); 495 } 496 497 public Target(int ii, float ff) { 498 System.out.println("Target constructor (IF)V : ii=" 499 + ii + " ff=" + ff); 500 anInt = ii; 501 } 502 503 public int myMethod(int intarg) throws NullPointerException, IOException { 504 System.out.println("myMethod (I)I"); 505 System.out.println(" arg=" + intarg + " anInt=" + anInt); 506 return 5; 507 } 508 509 public int myMethod(String[] strarg, float f, char c) { 510 System.out.println("myMethod: " + strarg[0] + " " + f + " " + c + " !"); 511 return 7; 512 } 513 514 public static void myNoargMethod() { 515 System.out.println("myNoargMethod ()V"); 516 } 517 518 public void throwingMethod() { 519 System.out.println("throwingMethod"); 520 throw new NullPointerException("gratuitous throw!"); 521 } 522 523 public void misc() { 524 System.out.println("misc"); 525 } 526 527 public int anInt; 528 public String string1 = "hey"; 529 public String string2 = "yo"; 530 public String string3 = "there"; 531 private String string4 = "naughty"; 532 public static final String constantString = "a constant string"; 533 private int aPrivateInt; 534 535 public final int cantTouchThis = 77; 536 537 public long pubLong = 0x1122334455667788L; 538 539 public static double staticDouble = 3.3; 540 } 541 542 class NoisyInit { 543 static { 544 System.out.println("NoisyInit is initializing"); 545 //Throwable th = new Throwable(); 546 //th.printStackTrace(); 547 } 548 } 549 550 class NoisyInitUser { 551 static { 552 System.out.println("NoisyInitUser is initializing"); 553 } 554 public void createNoisyInit(NoisyInit ni) {} 555 } 556