• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 import java.lang.reflect.*;
18 import java.io.IOException;
19 import java.util.Collections;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.Map;
23 
24 /**
25  * Reflection test.
26  */
27 public class Main {
28     private static boolean FULL_ACCESS_CHECKS = false;  // b/5861201
Main()29     public Main() {}
Main(ArrayList<Integer> stuff)30     public Main(ArrayList<Integer> stuff) {}
31 
printMethodInfo(Method meth)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 
printFieldInfo(Field field)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 
showStrings(Target instance)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 
checkAccess()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 
run()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             } catch (IllegalAccessException iae) {
339                 System.out.println("ERROR: set-final failed");
340             }
341             intVal = field.getInt(instance);
342             System.out.println("  cantTouchThis is now " + intVal);
343 
344             System.out.println("  " + field + " accessible=" + field.isAccessible());
345             field.setAccessible(true);
346             System.out.println("  " + field + " accessible=" + field.isAccessible());
347             field.setInt(instance, 87);     // exercise int version
348             intVal = field.getInt(instance);
349             System.out.println("  cantTouchThis is now " + intVal);
350             field.set(instance, 88);        // exercise Object version
351             intVal = field.getInt(instance);
352             System.out.println("  cantTouchThis is now " + intVal);
353 
354             Constructor<Target> cons;
355             Target targ;
356             Object[] args;
357 
358             cons = target.getConstructor(new Class[] { int.class,float.class });
359             args = new Object[] { new Integer(7), new Float(3.3333) };
360             System.out.println("cons modifiers=" + cons.getModifiers());
361             targ = cons.newInstance(args);
362             targ.myMethod(17);
363 
364         } catch (Exception ex) {
365             System.out.println("----- unexpected exception -----");
366             ex.printStackTrace();
367         }
368 
369         System.out.println("ReflectTest done!");
370     }
371 
checkType()372     public static void checkType() {
373         Method m;
374 
375         try {
376             m = Collections.class.getDeclaredMethod("checkType",
377                             Object.class, Class.class);
378         } catch (NoSuchMethodException nsme) {
379             nsme.printStackTrace();
380             return;
381         }
382         System.out.println(m + " accessible=" + m.isAccessible());
383         m.setAccessible(true);
384         System.out.println(m + " accessible=" + m.isAccessible());
385         try {
386             m.invoke(null, new Object(), Object.class);
387         } catch (IllegalAccessException iae) {
388             iae.printStackTrace();
389             return;
390         } catch (InvocationTargetException ite) {
391             ite.printStackTrace();
392             return;
393         }
394 
395         try {
396             String s = "Should be ignored";
397             m.invoke(s, new Object(), Object.class);
398         } catch (IllegalAccessException iae) {
399             iae.printStackTrace();
400             return;
401         } catch (InvocationTargetException ite) {
402             ite.printStackTrace();
403             return;
404         }
405 
406         try {
407             System.out.println("checkType invoking null");
408             m.invoke(null, new Object(), int.class);
409             System.out.println("ERROR: should throw InvocationTargetException");
410         } catch (InvocationTargetException ite) {
411             System.out.println("checkType got expected exception");
412         } catch (IllegalAccessException iae) {
413             iae.printStackTrace();
414             return;
415         }
416     }
417 
checkClinitForFields()418     public static void checkClinitForFields() throws Exception {
419       // Loading a class constant shouldn't run <clinit>.
420       System.out.println("calling const-class FieldNoisyInitUser.class");
421       Class niuClass = FieldNoisyInitUser.class;
422       System.out.println("called const-class FieldNoisyInitUser.class");
423 
424       // Getting the declared fields doesn't run <clinit>.
425       Field[] fields = niuClass.getDeclaredFields();
426       System.out.println("got fields");
427 
428       Field field = niuClass.getField("staticField");
429       System.out.println("got field");
430       field.get(null);
431       System.out.println("read field value");
432 
433       // FieldNoisyInitUser should now be initialized, but FieldNoisyInit shouldn't be initialized yet.
434       FieldNoisyInitUser niu = new FieldNoisyInitUser();
435       FieldNoisyInit ni = new FieldNoisyInit();
436 
437       System.out.println("");
438     }
439 
checkClinitForMethods()440     public static void checkClinitForMethods() throws Exception {
441       // Loading a class constant shouldn't run <clinit>.
442       System.out.println("calling const-class MethodNoisyInitUser.class");
443       Class niuClass = MethodNoisyInitUser.class;
444       System.out.println("called const-class MethodNoisyInitUser.class");
445 
446       // Getting the declared methods doesn't run <clinit>.
447       Method[] methods = niuClass.getDeclaredMethods();
448       System.out.println("got methods");
449 
450       Method method = niuClass.getMethod("staticMethod", (Class[]) null);
451       System.out.println("got method");
452       method.invoke(null);
453       System.out.println("invoked method");
454 
455       // MethodNoisyInitUser should now be initialized, but MethodNoisyInit shouldn't be initialized yet.
456       MethodNoisyInitUser niu = new MethodNoisyInitUser();
457       MethodNoisyInit ni = new MethodNoisyInit();
458 
459       System.out.println("");
460     }
461 
462 
463     /*
464      * Test some generic type stuff.
465      */
466     public List<String> dummy;
fancyMethod(ArrayList<String> blah)467     public Map<Integer,String> fancyMethod(ArrayList<String> blah) { return null; }
checkGeneric()468     public static void checkGeneric() {
469         Field field;
470         try {
471             field = Main.class.getField("dummy");
472         } catch (NoSuchFieldException nsfe) {
473             throw new RuntimeException(nsfe);
474         }
475         Type listType = field.getGenericType();
476         System.out.println("generic field: " + listType);
477 
478         Method method;
479         try {
480             method = Main.class.getMethod("fancyMethod",
481                 new Class[] { ArrayList.class });
482         } catch (NoSuchMethodException nsme) {
483             throw new RuntimeException(nsme);
484         }
485         Type[] parmTypes = method.getGenericParameterTypes();
486         Type ret = method.getGenericReturnType();
487         System.out.println("generic method " + method.getName() + " params='"
488             + stringifyTypeArray(parmTypes) + "' ret='" + ret + "'");
489 
490         Constructor ctor;
491         try {
492             ctor = Main.class.getConstructor(new Class[] { ArrayList.class });
493         } catch (NoSuchMethodException nsme) {
494             throw new RuntimeException(nsme);
495         }
496         parmTypes = ctor.getGenericParameterTypes();
497         System.out.println("generic ctor " + ctor.getName() + " params='"
498             + stringifyTypeArray(parmTypes) + "'");
499     }
500 
501     /*
502      * Convert an array of Type into a string.  Start with an array count.
503      */
stringifyTypeArray(Type[] types)504     private static String stringifyTypeArray(Type[] types) {
505         StringBuilder stb = new StringBuilder();
506         boolean first = true;
507 
508         stb.append("[" + types.length + "]");
509 
510         for (Type t: types) {
511             if (first) {
512                 stb.append(" ");
513                 first = false;
514             } else {
515                 stb.append(", ");
516             }
517             stb.append(t.toString());
518         }
519 
520         return stb.toString();
521     }
522 
checkUnique()523     public static void checkUnique() {
524         Field field1, field2;
525         try {
526             field1 = Main.class.getField("dummy");
527             field2 = Main.class.getField("dummy");
528         } catch (NoSuchFieldException nsfe) {
529             throw new RuntimeException(nsfe);
530         }
531         if (field1 == field2) {
532             System.out.println("ERROR: fields shouldn't have reference equality");
533         } else {
534             System.out.println("fields are unique");
535         }
536         if (field1.hashCode() == field2.hashCode() && field1.equals(field2)) {
537             System.out.println("fields are .equals");
538         } else {
539             System.out.println("ERROR: fields fail equality");
540         }
541         Method method1, method2;
542         try {
543             method1 = Main.class.getMethod("fancyMethod", new Class[] { ArrayList.class });
544             method2 = Main.class.getMethod("fancyMethod", new Class[] { ArrayList.class });
545         } catch (NoSuchMethodException nsme) {
546             throw new RuntimeException(nsme);
547         }
548         if (method1 == method2) {
549             System.out.println("ERROR: methods shouldn't have reference equality");
550         } else {
551             System.out.println("methods are unique");
552         }
553         if (method1.hashCode() == method2.hashCode() && method1.equals(method2)) {
554             System.out.println("methods are .equals");
555         } else {
556             System.out.println("ERROR: methods fail equality");
557         }
558     }
559 
main(String[] args)560     public static void main(String[] args) throws Exception {
561         Main test = new Main();
562         test.run();
563 
564         checkAccess();
565         checkType();
566         checkClinitForFields();
567         checkClinitForMethods();
568         checkGeneric();
569         checkUnique();
570     }
571 }
572 
573 
574 class SuperTarget {
SuperTarget()575     public SuperTarget() {
576         System.out.println("SuperTarget constructor ()V");
577         superInt = 1010101;
578         superClassInt = 1010102;
579     }
580 
myMethod(float floatArg)581     public int myMethod(float floatArg) {
582         System.out.println("myMethod (F)I " + floatArg);
583         return 6;
584     }
585 
586     public int superInt;
587     public static int superClassInt;
588 }
589 
590 class Target extends SuperTarget {
Target()591     public Target() {
592         System.out.println("Target constructor ()V");
593     }
594 
Target(int ii, float ff)595     public Target(int ii, float ff) {
596         System.out.println("Target constructor (IF)V : ii="
597             + ii + " ff=" + ff);
598         anInt = ii;
599     }
600 
myMethod(int intarg)601     public int myMethod(int intarg) throws NullPointerException, IOException {
602         System.out.println("myMethod (I)I");
603         System.out.println(" arg=" + intarg + " anInt=" + anInt);
604         return 5;
605     }
606 
myMethod(String[] strarg, float f, char c)607     public int myMethod(String[] strarg, float f, char c) {
608         System.out.println("myMethod: " + strarg[0] + " " + f + " " + c + " !");
609         return 7;
610     }
611 
myNoargMethod()612     public static void myNoargMethod() {
613         System.out.println("myNoargMethod ()V");
614     }
615 
throwingMethod()616     public void throwingMethod() {
617         System.out.println("throwingMethod");
618         throw new NullPointerException("gratuitous throw!");
619     }
620 
misc()621     public void misc() {
622         System.out.println("misc");
623     }
624 
625     public int anInt;
626     public String string1 = "hey";
627     public String string2 = "yo";
628     public String string3 = "there";
629     private String string4 = "naughty";
630     public static final String constantString = "a constant string";
631     private int aPrivateInt;
632 
633     public final int cantTouchThis = 77;
634 
635     public long pubLong = 0x1122334455667788L;
636 
637     public static double staticDouble = 3.3;
638 }
639 
640 class FieldNoisyInit {
641   static {
642     System.out.println("FieldNoisyInit is initializing");
643     //Throwable th = new Throwable();
644     //th.printStackTrace();
645   }
646 }
647 
648 class FieldNoisyInitUser {
649   static {
650     System.out.println("FieldNoisyInitUser is initializing");
651   }
652   public static int staticField;
653   public static FieldNoisyInit noisy;
654 }
655 
656 class MethodNoisyInit {
657   static {
658     System.out.println("MethodNoisyInit is initializing");
659     //Throwable th = new Throwable();
660     //th.printStackTrace();
661   }
662 }
663 
664 class MethodNoisyInitUser {
665   static {
666     System.out.println("MethodNoisyInitUser is initializing");
667   }
staticMethod()668   public static void staticMethod() {}
createMethodNoisyInit(MethodNoisyInit ni)669   public void createMethodNoisyInit(MethodNoisyInit ni) {}
670 }
671