Main.java revision 63f5b9e8f660ae761901072821ece30d87891644
1/* 2 * Copyright (C) 2006 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 17import java.lang.reflect.*; 18import java.io.IOException; 19import java.util.Collections; 20import java.util.ArrayList; 21import java.util.List; 22import java.util.Map; 23 24/** 25 * Reflection test. 26 */ 27public class Main { 28 private static boolean FULL_ACCESS_CHECKS = false; // b/5861201 29 public Main() {} 30 public Main(ArrayList<Integer> stuff) {} 31 32 void printMethodInfo(Method meth) { 33 Class[] params, exceptions; 34 int i; 35 36 System.out.println("Method name is " + meth.getName()); 37 System.out.println(" Declaring class is " 38 + meth.getDeclaringClass().getName()); 39 params = meth.getParameterTypes(); 40 for (i = 0; i < params.length; i++) 41 System.out.println(" Arg " + i + ": " + params[i].getName()); 42 exceptions = meth.getExceptionTypes(); 43 for (i = 0; i < exceptions.length; i++) 44 System.out.println(" Exc " + i + ": " + exceptions[i].getName()); 45 System.out.println(" Return type is " + meth.getReturnType().getName()); 46 System.out.println(" Access flags are 0x" 47 + Integer.toHexString(meth.getModifiers())); 48 //System.out.println(" GenericStr is " + meth.toGenericString()); 49 } 50 51 void printFieldInfo(Field field) { 52 System.out.println("Field name is " + field.getName()); 53 System.out.println(" Declaring class is " 54 + field.getDeclaringClass().getName()); 55 System.out.println(" Field type is " + field.getType().getName()); 56 System.out.println(" Access flags are 0x" 57 + Integer.toHexString(field.getModifiers())); 58 } 59 60 private void showStrings(Target instance) 61 throws NoSuchFieldException, IllegalAccessException { 62 63 Class target = Target.class; 64 String one, two, three, four; 65 Field field = null; 66 67 field = target.getField("string1"); 68 one = (String) field.get(instance); 69 70 field = target.getField("string2"); 71 two = (String) field.get(instance); 72 73 field = target.getField("string3"); 74 three = (String) field.get(instance); 75 76 System.out.println(" ::: " + one + ":" + two + ":" + three); 77 } 78 79 public static void checkAccess() { 80 try { 81 Class target = otherpackage.Other.class; 82 Object instance = new otherpackage.Other(); 83 Method meth; 84 85 meth = target.getMethod("publicMethod", (Class[]) null); 86 meth.invoke(instance); 87 88 try { 89 meth = target.getMethod("packageMethod", (Class[]) null); 90 System.err.println("succeeded on package-scope method"); 91 } catch (NoSuchMethodException nsme) { 92 // good 93 } 94 95 96 instance = otherpackage.Other.getInnerClassInstance(); 97 target = instance.getClass(); 98 meth = target.getMethod("innerMethod", (Class[]) null); 99 try { 100 if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); } 101 meth.invoke(instance); 102 System.err.println("inner-method invoke unexpectedly worked"); 103 } catch (IllegalAccessException iae) { 104 // good 105 } 106 107 Field field = target.getField("innerField"); 108 try { 109 int x = field.getInt(instance); 110 if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); } 111 System.err.println("field get unexpectedly worked: " + x); 112 } catch (IllegalAccessException iae) { 113 // good 114 } 115 } catch (Exception ex) { 116 System.out.println("----- unexpected exception -----"); 117 ex.printStackTrace(); 118 } 119 } 120 121 public void run() { 122 Class target = Target.class; 123 Method meth = null; 124 Field field = null; 125 boolean excep; 126 127 try { 128 meth = target.getMethod("myMethod", new Class[] { int.class }); 129 130 if (meth.getDeclaringClass() != target) 131 throw new RuntimeException(); 132 printMethodInfo(meth); 133 134 meth = target.getMethod("myMethod", new Class[] { float.class }); 135 printMethodInfo(meth); 136 137 meth = target.getMethod("myNoargMethod", (Class[]) null); 138 printMethodInfo(meth); 139 140 meth = target.getMethod("myMethod", 141 new Class[] { String[].class, float.class, char.class }); 142 printMethodInfo(meth); 143 144 Target instance = new Target(); 145 Object[] argList = new Object[] { 146 new String[] { "hi there" }, 147 new Float(3.1415926f), 148 new Character('Q') 149 }; 150 System.out.println("Before, float is " 151 + ((Float)argList[1]).floatValue()); 152 153 Integer boxval; 154 boxval = (Integer) meth.invoke(instance, argList); 155 System.out.println("Result of invoke: " + boxval.intValue()); 156 157 System.out.println("Calling no-arg void-return method"); 158 meth = target.getMethod("myNoargMethod", (Class[]) null); 159 meth.invoke(instance, (Object[]) null); 160 161 /* try invoking a method that throws an exception */ 162 meth = target.getMethod("throwingMethod", (Class[]) null); 163 try { 164 meth.invoke(instance, (Object[]) null); 165 System.out.println("GLITCH: didn't throw"); 166 } catch (InvocationTargetException ite) { 167 System.out.println("Invoke got expected exception:"); 168 System.out.println(ite.getClass().getName()); 169 System.out.println(ite.getCause()); 170 } 171 catch (Exception ex) { 172 System.out.println("GLITCH: invoke got wrong exception:"); 173 ex.printStackTrace(); 174 } 175 System.out.println(""); 176 177 178 field = target.getField("string1"); 179 if (field.getDeclaringClass() != target) 180 throw new RuntimeException(); 181 printFieldInfo(field); 182 String strVal = (String) field.get(instance); 183 System.out.println(" string1 value is '" + strVal + "'"); 184 185 showStrings(instance); 186 187 field.set(instance, new String("a new string")); 188 strVal = (String) field.get(instance); 189 System.out.println(" string1 value is now '" + strVal + "'"); 190 191 showStrings(instance); 192 193 try { 194 field.set(instance, new Object()); 195 System.out.println("WARNING: able to store Object into String"); 196 } 197 catch (IllegalArgumentException iae) { 198 System.out.println(" got expected illegal obj store exc"); 199 } 200 201 202 try { 203 String four; 204 field = target.getField("string4"); 205 four = (String) field.get(instance); 206 System.out.println("WARNING: able to access string4: " 207 + four); 208 } 209 catch (IllegalAccessException iae) { 210 System.out.println(" got expected access exc"); 211 } 212 catch (NoSuchFieldException nsfe) { 213 System.out.println(" got the other expected access exc"); 214 } 215 try { 216 String three; 217 field = target.getField("string3"); 218 three = (String) field.get(this); 219 System.out.println("WARNING: able to get string3 in wrong obj: " 220 + three); 221 } 222 catch (IllegalArgumentException iae) { 223 System.out.println(" got expected arg exc"); 224 } 225 226 /* 227 * Try setting a field to null. 228 */ 229 String four; 230 field = target.getDeclaredField("string3"); 231 field.set(instance, null); 232 233 /* 234 * Do some stuff with long. 235 */ 236 long longVal; 237 field = target.getField("pubLong"); 238 longVal = field.getLong(instance); 239 System.out.println("pubLong initial value is " + 240 Long.toHexString(longVal)); 241 field.setLong(instance, 0x9988776655443322L); 242 longVal = field.getLong(instance); 243 System.out.println("pubLong new value is " + 244 Long.toHexString(longVal)); 245 246 247 field = target.getField("superInt"); 248 if (field.getDeclaringClass() == target) 249 throw new RuntimeException(); 250 printFieldInfo(field); 251 int intVal = field.getInt(instance); 252 System.out.println(" superInt value is " + intVal); 253 Integer boxedIntVal = (Integer) field.get(instance); 254 System.out.println(" superInt boxed is " + boxedIntVal); 255 256 field.set(instance, new Integer(20202)); 257 intVal = field.getInt(instance); 258 System.out.println(" superInt value is now " + intVal); 259 field.setShort(instance, (short)30303); 260 intVal = field.getInt(instance); 261 System.out.println(" superInt value (from short) is now " +intVal); 262 field.setInt(instance, 40404); 263 intVal = field.getInt(instance); 264 System.out.println(" superInt value is now " + intVal); 265 try { 266 field.set(instance, new Long(123)); 267 System.out.println("FAIL: expected exception not thrown"); 268 } 269 catch (IllegalArgumentException iae) { 270 System.out.println(" got expected long->int failure"); 271 } 272 try { 273 field.setLong(instance, 123); 274 System.out.println("FAIL: expected exception not thrown"); 275 } 276 catch (IllegalArgumentException iae) { 277 System.out.println(" got expected long->int failure"); 278 } 279 try { 280 field.set(instance, new String("abc")); 281 System.out.println("FAIL: expected exception not thrown"); 282 } 283 catch (IllegalArgumentException iae) { 284 System.out.println(" got expected string->int failure"); 285 } 286 287 try { 288 field.getShort(instance); 289 System.out.println("FAIL: expected exception not thrown"); 290 } 291 catch (IllegalArgumentException iae) { 292 System.out.println(" got expected int->short failure"); 293 } 294 295 field = target.getField("superClassInt"); 296 printFieldInfo(field); 297 int superClassIntVal = field.getInt(instance); 298 System.out.println(" superClassInt value is " + superClassIntVal); 299 300 field = target.getField("staticDouble"); 301 printFieldInfo(field); 302 double staticDoubleVal = field.getDouble(null); 303 System.out.println(" staticDoubleVal value is " + staticDoubleVal); 304 305 try { 306 field.getLong(instance); 307 System.out.println("FAIL: expected exception not thrown"); 308 } 309 catch (IllegalArgumentException iae) { 310 System.out.println(" got expected double->long failure"); 311 } 312 313 excep = false; 314 try { 315 field = target.getField("aPrivateInt"); 316 printFieldInfo(field); 317 } 318 catch (NoSuchFieldException nsfe) { 319 System.out.println("as expected: aPrivateInt not found"); 320 excep = true; 321 } 322 if (!excep) 323 System.out.println("BUG: got aPrivateInt"); 324 325 326 field = target.getField("constantString"); 327 printFieldInfo(field); 328 String val = (String) field.get(instance); 329 System.out.println(" Constant test value is " + val); 330 331 332 field = target.getField("cantTouchThis"); 333 printFieldInfo(field); 334 intVal = field.getInt(instance); 335 System.out.println(" cantTouchThis is " + intVal); 336 try { 337 field.setInt(instance, 99); 338 System.out.println("ERROR: set-final did not throw exception"); 339 } catch (IllegalAccessException iae) { 340 System.out.println(" as expected: set-final throws exception"); 341 } 342 intVal = field.getInt(instance); 343 System.out.println(" cantTouchThis is still " + intVal); 344 345 System.out.println(" " + field + " accessible=" + field.isAccessible()); 346 field.setAccessible(true); 347 System.out.println(" " + field + " accessible=" + field.isAccessible()); 348 field.setInt(instance, 87); // exercise int version 349 intVal = field.getInt(instance); 350 System.out.println(" cantTouchThis is now " + intVal); 351 field.set(instance, 88); // exercise Object version 352 intVal = field.getInt(instance); 353 System.out.println(" cantTouchThis is now " + intVal); 354 355 Constructor<Target> cons; 356 Target targ; 357 Object[] args; 358 359 cons = target.getConstructor(new Class[] { int.class,float.class }); 360 args = new Object[] { new Integer(7), new Float(3.3333) }; 361 System.out.println("cons modifiers=" + cons.getModifiers()); 362 targ = cons.newInstance(args); 363 targ.myMethod(17); 364 365 try { 366 Thrower thrower = Thrower.class.newInstance(); 367 System.out.println("ERROR: Class.newInstance did not throw exception"); 368 } catch (UnsupportedOperationException uoe) { 369 System.out.println("got expected exception for Class.newInstance"); 370 } catch (Exception e) { 371 System.out.println("ERROR: Class.newInstance got unexpected exception: " + 372 e.getClass().getName()); 373 } 374 375 try { 376 Constructor<Thrower> constructor = Thrower.class.getDeclaredConstructor(); 377 Thrower thrower = constructor.newInstance(); 378 System.out.println("ERROR: Constructor.newInstance did not throw exception"); 379 } catch (InvocationTargetException ite) { 380 System.out.println("got expected exception for Constructor.newInstance"); 381 } catch (Exception e) { 382 System.out.println("ERROR: Constructor.newInstance got unexpected exception: " + 383 e.getClass().getName()); 384 } 385 386 } catch (Exception ex) { 387 System.out.println("----- unexpected exception -----"); 388 ex.printStackTrace(); 389 } 390 391 System.out.println("ReflectTest done!"); 392 } 393 394 public static void checkType() { 395 Method m; 396 397 try { 398 m = Collections.class.getDeclaredMethod("checkType", 399 Object.class, Class.class); 400 } catch (NoSuchMethodException nsme) { 401 nsme.printStackTrace(); 402 return; 403 } 404 System.out.println(m + " accessible=" + m.isAccessible()); 405 m.setAccessible(true); 406 System.out.println(m + " accessible=" + m.isAccessible()); 407 try { 408 m.invoke(null, new Object(), Object.class); 409 } catch (IllegalAccessException iae) { 410 iae.printStackTrace(); 411 return; 412 } catch (InvocationTargetException ite) { 413 ite.printStackTrace(); 414 return; 415 } 416 417 try { 418 String s = "Should be ignored"; 419 m.invoke(s, new Object(), Object.class); 420 } catch (IllegalAccessException iae) { 421 iae.printStackTrace(); 422 return; 423 } catch (InvocationTargetException ite) { 424 ite.printStackTrace(); 425 return; 426 } 427 428 try { 429 System.out.println("checkType invoking null"); 430 m.invoke(null, new Object(), int.class); 431 System.out.println("ERROR: should throw InvocationTargetException"); 432 } catch (InvocationTargetException ite) { 433 System.out.println("checkType got expected exception"); 434 } catch (IllegalAccessException iae) { 435 iae.printStackTrace(); 436 return; 437 } 438 } 439 440 public static void checkClinitForFields() throws Exception { 441 // Loading a class constant shouldn't run <clinit>. 442 System.out.println("calling const-class FieldNoisyInitUser.class"); 443 Class niuClass = FieldNoisyInitUser.class; 444 System.out.println("called const-class FieldNoisyInitUser.class"); 445 446 // Getting the declared fields doesn't run <clinit>. 447 Field[] fields = niuClass.getDeclaredFields(); 448 System.out.println("got fields"); 449 450 Field field = niuClass.getField("staticField"); 451 System.out.println("got field"); 452 field.get(null); 453 System.out.println("read field value"); 454 455 // FieldNoisyInitUser should now be initialized, but FieldNoisyInit shouldn't be initialized yet. 456 FieldNoisyInitUser niu = new FieldNoisyInitUser(); 457 FieldNoisyInit ni = new FieldNoisyInit(); 458 459 System.out.println(""); 460 } 461 462 public static void checkClinitForMethods() throws Exception { 463 // Loading a class constant shouldn't run <clinit>. 464 System.out.println("calling const-class MethodNoisyInitUser.class"); 465 Class niuClass = MethodNoisyInitUser.class; 466 System.out.println("called const-class MethodNoisyInitUser.class"); 467 468 // Getting the declared methods doesn't run <clinit>. 469 Method[] methods = niuClass.getDeclaredMethods(); 470 System.out.println("got methods"); 471 472 Method method = niuClass.getMethod("staticMethod", (Class[]) null); 473 System.out.println("got method"); 474 method.invoke(null); 475 System.out.println("invoked method"); 476 477 // MethodNoisyInitUser should now be initialized, but MethodNoisyInit shouldn't be initialized yet. 478 MethodNoisyInitUser niu = new MethodNoisyInitUser(); 479 MethodNoisyInit ni = new MethodNoisyInit(); 480 481 System.out.println(""); 482 } 483 484 485 /* 486 * Test some generic type stuff. 487 */ 488 public List<String> dummy; 489 public Map<Integer,String> fancyMethod(ArrayList<String> blah) { return null; } 490 public static void checkGeneric() { 491 Field field; 492 try { 493 field = Main.class.getField("dummy"); 494 } catch (NoSuchFieldException nsfe) { 495 throw new RuntimeException(nsfe); 496 } 497 Type listType = field.getGenericType(); 498 System.out.println("generic field: " + listType); 499 500 Method method; 501 try { 502 method = Main.class.getMethod("fancyMethod", 503 new Class[] { ArrayList.class }); 504 } catch (NoSuchMethodException nsme) { 505 throw new RuntimeException(nsme); 506 } 507 Type[] parmTypes = method.getGenericParameterTypes(); 508 Type ret = method.getGenericReturnType(); 509 System.out.println("generic method " + method.getName() + " params='" 510 + stringifyTypeArray(parmTypes) + "' ret='" + ret + "'"); 511 512 Constructor ctor; 513 try { 514 ctor = Main.class.getConstructor(new Class[] { ArrayList.class }); 515 } catch (NoSuchMethodException nsme) { 516 throw new RuntimeException(nsme); 517 } 518 parmTypes = ctor.getGenericParameterTypes(); 519 System.out.println("generic ctor " + ctor.getName() + " params='" 520 + stringifyTypeArray(parmTypes) + "'"); 521 } 522 523 /* 524 * Convert an array of Type into a string. Start with an array count. 525 */ 526 private static String stringifyTypeArray(Type[] types) { 527 StringBuilder stb = new StringBuilder(); 528 boolean first = true; 529 530 stb.append("[" + types.length + "]"); 531 532 for (Type t: types) { 533 if (first) { 534 stb.append(" "); 535 first = false; 536 } else { 537 stb.append(", "); 538 } 539 stb.append(t.toString()); 540 } 541 542 return stb.toString(); 543 } 544 545 public static void checkUnique() { 546 Field field1, field2; 547 try { 548 field1 = Main.class.getField("dummy"); 549 field2 = Main.class.getField("dummy"); 550 } catch (NoSuchFieldException nsfe) { 551 throw new RuntimeException(nsfe); 552 } 553 if (field1 == field2) { 554 System.out.println("ERROR: fields shouldn't have reference equality"); 555 } else { 556 System.out.println("fields are unique"); 557 } 558 if (field1.hashCode() == field2.hashCode() && field1.equals(field2)) { 559 System.out.println("fields are .equals"); 560 } else { 561 System.out.println("ERROR: fields fail equality"); 562 } 563 Method method1, method2; 564 try { 565 method1 = Main.class.getMethod("fancyMethod", new Class[] { ArrayList.class }); 566 method2 = Main.class.getMethod("fancyMethod", new Class[] { ArrayList.class }); 567 } catch (NoSuchMethodException nsme) { 568 throw new RuntimeException(nsme); 569 } 570 if (method1 == method2) { 571 System.out.println("ERROR: methods shouldn't have reference equality"); 572 } else { 573 System.out.println("methods are unique"); 574 } 575 if (method1.hashCode() == method2.hashCode() && method1.equals(method2)) { 576 System.out.println("methods are .equals"); 577 } else { 578 System.out.println("ERROR: methods fail equality"); 579 } 580 } 581 582 public static void main(String[] args) throws Exception { 583 Main test = new Main(); 584 test.run(); 585 586 checkAccess(); 587 checkType(); 588 checkClinitForFields(); 589 checkClinitForMethods(); 590 checkGeneric(); 591 checkUnique(); 592 } 593} 594 595 596class SuperTarget { 597 public SuperTarget() { 598 System.out.println("SuperTarget constructor ()V"); 599 superInt = 1010101; 600 superClassInt = 1010102; 601 } 602 603 public int myMethod(float floatArg) { 604 System.out.println("myMethod (F)I " + floatArg); 605 return 6; 606 } 607 608 public int superInt; 609 public static int superClassInt; 610} 611 612class Target extends SuperTarget { 613 public Target() { 614 System.out.println("Target constructor ()V"); 615 } 616 617 public Target(int ii, float ff) { 618 System.out.println("Target constructor (IF)V : ii=" 619 + ii + " ff=" + ff); 620 anInt = ii; 621 } 622 623 public int myMethod(int intarg) throws NullPointerException, IOException { 624 System.out.println("myMethod (I)I"); 625 System.out.println(" arg=" + intarg + " anInt=" + anInt); 626 return 5; 627 } 628 629 public int myMethod(String[] strarg, float f, char c) { 630 System.out.println("myMethod: " + strarg[0] + " " + f + " " + c + " !"); 631 return 7; 632 } 633 634 public static void myNoargMethod() { 635 System.out.println("myNoargMethod ()V"); 636 } 637 638 public void throwingMethod() { 639 System.out.println("throwingMethod"); 640 throw new NullPointerException("gratuitous throw!"); 641 } 642 643 public void misc() { 644 System.out.println("misc"); 645 } 646 647 public int anInt; 648 public String string1 = "hey"; 649 public String string2 = "yo"; 650 public String string3 = "there"; 651 private String string4 = "naughty"; 652 public static final String constantString = "a constant string"; 653 private int aPrivateInt; 654 655 public final int cantTouchThis = 77; 656 657 public long pubLong = 0x1122334455667788L; 658 659 public static double staticDouble = 3.3; 660} 661 662class FieldNoisyInit { 663 static { 664 System.out.println("FieldNoisyInit is initializing"); 665 //Throwable th = new Throwable(); 666 //th.printStackTrace(); 667 } 668} 669 670class FieldNoisyInitUser { 671 static { 672 System.out.println("FieldNoisyInitUser is initializing"); 673 } 674 public static int staticField; 675 public static FieldNoisyInit noisy; 676} 677 678class MethodNoisyInit { 679 static { 680 System.out.println("MethodNoisyInit is initializing"); 681 //Throwable th = new Throwable(); 682 //th.printStackTrace(); 683 } 684} 685 686class MethodNoisyInitUser { 687 static { 688 System.out.println("MethodNoisyInitUser is initializing"); 689 } 690 public static void staticMethod() {} 691 public void createMethodNoisyInit(MethodNoisyInit ni) {} 692} 693 694class Thrower { 695 public Thrower() throws UnsupportedOperationException { 696 throw new UnsupportedOperationException(); 697 } 698} 699