1 /*
2  * Copyright (C) 2011 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.util.*;
19 
20 class Main {
21   private static boolean z = true;
22   private static byte b = 8;
23   private static char c = '\u2714';
24   private static double d = Math.PI;
25   private static float f = 3.14f;
26   private static int i = 32;
27   private static long j = 0x0123456789abcdefL;
28   private static short s = 16;
29 
testFieldReflection()30   public static void testFieldReflection() throws Exception {
31     Field f;
32 
33     f = Main.class.getDeclaredField("z");
34     System.out.println(f.getBoolean(null));
35     f = Main.class.getDeclaredField("b");
36     System.out.println(f.getByte(null));
37     f = Main.class.getDeclaredField("c");
38     System.out.println(f.getChar(null));
39     f = Main.class.getDeclaredField("d");
40     System.out.println(f.getDouble(null));
41     f = Main.class.getDeclaredField("f");
42     System.out.println(f.getFloat(null));
43     f = Main.class.getDeclaredField("i");
44     System.out.println(f.getInt(null));
45     f = Main.class.getDeclaredField("j");
46     System.out.println(f.getLong(null));
47     f = Main.class.getDeclaredField("s");
48     System.out.println(f.getShort(null));
49 
50     f = Main.class.getDeclaredField("z");
51     f.setBoolean(null, false);
52     f = Main.class.getDeclaredField("b");
53     f.setByte(null, (byte) 7);
54     f = Main.class.getDeclaredField("c");
55     f.setChar(null, 'y');
56     f = Main.class.getDeclaredField("d");
57     f.setDouble(null, 2.7);
58     f = Main.class.getDeclaredField("f");
59     f.setFloat(null, 2.7f);
60     f = Main.class.getDeclaredField("i");
61     f.setInt(null, 31);
62     f = Main.class.getDeclaredField("j");
63     f.setLong(null, 63);
64     f = Main.class.getDeclaredField("s");
65     f.setShort(null, (short) 15);
66 
67     f = Main.class.getDeclaredField("z");
68     System.out.println(f.getBoolean(null));
69     f = Main.class.getDeclaredField("b");
70     System.out.println(f.getByte(null));
71     f = Main.class.getDeclaredField("c");
72     System.out.println(f.getChar(null));
73     f = Main.class.getDeclaredField("d");
74     System.out.println(f.getDouble(null));
75     f = Main.class.getDeclaredField("f");
76     System.out.println(f.getFloat(null));
77     f = Main.class.getDeclaredField("i");
78     System.out.println(f.getInt(null));
79     f = Main.class.getDeclaredField("j");
80     System.out.println(f.getLong(null));
81     f = Main.class.getDeclaredField("s");
82     System.out.println(f.getShort(null));
83 
84     f = Main.class.getDeclaredField("z");
85     f.set(null, Boolean.valueOf(true));
86     f = Main.class.getDeclaredField("b");
87     f.set(null, Byte.valueOf((byte) 6));
88     f = Main.class.getDeclaredField("c");
89     f.set(null, Character.valueOf('z'));
90     f = Main.class.getDeclaredField("d");
91     f.set(null, Double.valueOf(1.3));
92     f = Main.class.getDeclaredField("f");
93     f.set(null, Float.valueOf(1.3f));
94     f = Main.class.getDeclaredField("i");
95     f.set(null, Integer.valueOf(30));
96     f = Main.class.getDeclaredField("j");
97     f.set(null, Long.valueOf(62));
98     f.set(null, Integer.valueOf(62));
99     f = Main.class.getDeclaredField("s");
100     f.set(null, Short.valueOf((short) 14));
101 
102     f = Main.class.getDeclaredField("z");
103     System.out.println(f.getBoolean(null));
104     f = Main.class.getDeclaredField("b");
105     System.out.println(f.getByte(null));
106     f = Main.class.getDeclaredField("c");
107     System.out.println(f.getChar(null));
108     f = Main.class.getDeclaredField("d");
109     System.out.println(f.getDouble(null));
110     f = Main.class.getDeclaredField("f");
111     System.out.println(f.getFloat(null));
112     f = Main.class.getDeclaredField("i");
113     System.out.println(f.getInt(null));
114     f = Main.class.getDeclaredField("j");
115     System.out.println(f.getLong(null));
116     f = Main.class.getDeclaredField("s");
117     System.out.println(f.getShort(null));
118 
119     try {
120       f = Main.class.getDeclaredField("s");
121       f.set(null, Integer.valueOf(14));
122       System.out.println("************* should have thrown!");
123     } catch (IllegalArgumentException expected) {
124       System.out.println("got expected IllegalArgumentException");
125     }
126 
127     f = Main.class.getDeclaredField("z");
128     show(f.get(null));
129     f = Main.class.getDeclaredField("b");
130     show(f.get(null));
131     f = Main.class.getDeclaredField("c");
132     show(f.get(null));
133     f = Main.class.getDeclaredField("d");
134     show(f.get(null));
135     f = Main.class.getDeclaredField("f");
136     show(f.get(null));
137     f = Main.class.getDeclaredField("i");
138     show(f.get(null));
139     f = Main.class.getDeclaredField("j");
140     show(f.get(null));
141     f = Main.class.getDeclaredField("s");
142     show(f.get(null));
143 
144     /*
145     private static boolean z = true;
146     private static byte b = 8;
147     private static char c = '\u2714';
148     private static double d = Math.PI;
149     private static float f = 3.14f;
150     private static int i = 32;
151     private static long j = 0x0123456789abcdefL;
152     private static short s = 16;
153     */
154   }
155 
show(Object o)156   private static void show(Object o) {
157     System.out.println(o + " (" + (o != null ? o.getClass() : "null") + ")");
158   }
159 
160   /**
161    * Sorts the input array using the comparator and returns the sorted array.
162    */
sort(Object[] objects, Comparator<Object> comp)163   private static Object[] sort(Object[] objects, Comparator<Object> comp) {
164     Arrays.sort(objects, comp);
165     return objects;
166   }
167 
testMethodReflection()168   public static void testMethodReflection() throws Exception {
169     Comparator<Object> comp = new Comparator<Object>() {
170       public int compare(Object a, Object b) {
171         return a.toString().compareTo(b.toString());
172       }
173       public boolean equals(Object b) {
174         return this == b;
175       }
176     };
177 
178     // Sort the return values by their string values since the order is undefined by the spec.
179     System.out.println(Arrays.toString(sort(String.class.getDeclaredConstructors(), comp)));
180     System.out.println(Arrays.toString(sort(String.class.getDeclaredFields(), comp)));
181     System.out.println(Arrays.toString(sort(String.class.getDeclaredMethods(), comp)));
182 
183     System.out.println(Arrays.toString(Main.class.getInterfaces()));
184     System.out.println(Arrays.toString(String.class.getInterfaces()));
185 
186     System.out.println(Main.class.getModifiers());
187     System.out.println(String.class.getModifiers());
188 
189     System.out.println(String.class.isAssignableFrom(Object.class));
190     System.out.println(Object.class.isAssignableFrom(String.class));
191 
192     System.out.println(String.class.isInstance("hello"));
193     System.out.println(String.class.isInstance(123));
194 
195     Method m;
196 
197     m = Main.class.getDeclaredMethod("IV", int.class);
198     System.out.println(Arrays.toString(m.getParameterTypes()));
199     show(m.invoke(null, 4444));
200     System.out.println(Arrays.toString(m.getParameterTypes()));
201 
202     m = Main.class.getDeclaredMethod("IIV", int.class, int.class);
203     System.out.println(Arrays.toString(m.getParameterTypes()));
204     show(m.invoke(null, 1111, 2222));
205 
206     m = Main.class.getDeclaredMethod("III", int.class, int.class);
207     System.out.println(Arrays.toString(m.getParameterTypes()));
208     show(m.invoke(null, 1111, 2222));
209 
210     m = Main.class.getDeclaredMethod("sumArray", int[].class);
211     System.out.println(Arrays.toString(m.getParameterTypes()));
212     show(m.invoke(null, new int[] { 1, 2, 3, 4 }));
213 
214     m = Main.class.getDeclaredMethod("concat", String[].class);
215     System.out.println(Arrays.toString(m.getParameterTypes()));
216     show(m.invoke(null, (Object) new String[] { "h", "e", "l", "l", "o" }));
217 
218     m = Main.class.getDeclaredMethod("ZBCDFIJSV", boolean.class, byte.class, char.class, double.class, float.class, int.class, long.class, short.class);
219     System.out.println(Arrays.toString(m.getParameterTypes()));
220     show(m.invoke(null, true, (byte) 0, '1', 2, 3, 4, 5, (short) 6));
221 
222     m = Main.class.getDeclaredMethod("ZBCDLFIJSV", boolean.class, byte.class, char.class, double.class, String.class, float.class, int.class, long.class, short.class);
223     System.out.println(Arrays.toString(m.getParameterTypes()));
224     show(m.invoke(null, true, (byte) 0, '1', 2, "hello world", 3, 4, 5, (short) 6));
225 
226     try {
227       m = Main.class.getDeclaredMethod("thrower");
228       System.out.println(Arrays.toString(m.getParameterTypes()));
229       show(m.invoke(null));
230       System.out.println("************* should have thrown!");
231     } catch (InvocationTargetException expected) {
232       System.out.println("got expected InvocationTargetException");
233     }
234   }
235 
thrower()236   private static void thrower() {
237     throw new ArithmeticException("surprise!");
238   }
239 
sumArray(int[] xs)240   private static int sumArray(int[] xs) {
241     int result = 0;
242     for (int x : xs) {
243       result += x;
244     }
245     return result;
246   }
247 
concat(String[] strings)248   private static String concat(String[] strings) {
249     String result = "";
250     for (String s : strings) {
251       result += s;
252     }
253     return result;
254   }
255 
IV(int i)256   private static void IV(int i) {
257     System.out.println(i);
258   }
259 
IIV(int i, int j)260   private static void IIV(int i, int j) {
261     System.out.println(i + " " + j);
262   }
263 
III(int i, int j)264   private static int III(int i, int j) {
265     System.out.println(i + " " + j);
266     return i + j;
267   }
268 
ZBCDFIJSV(boolean z, byte b, char c, double d, float f, int i, long l, short s)269   private static void ZBCDFIJSV(boolean z, byte b, char c, double d, float f, int i, long l, short s) {
270     System.out.println(z + " " + b + " " + c + " " + d + " " + f + " " + i + " " + l + " " + s);
271   }
272 
ZBCDLFIJSV(boolean z, byte b, char c, double d, String string, float f, int i, long l, short s)273   private static void ZBCDLFIJSV(boolean z, byte b, char c, double d, String string, float f, int i, long l, short s) {
274     System.out.println(z + " " + b + " " + c + " " + d + " " + " " + string + " " + f + " " + i + " " + l + " " + s);
275   }
276 
testConstructorReflection()277   public static void testConstructorReflection() throws Exception {
278     Constructor<String> ctor = String.class.getConstructor();
279     show(ctor.newInstance());
280 
281     ctor = String.class.getConstructor(char[].class, int.class, int.class);
282     show(ctor.newInstance(new char[] { '\u2714', 'y', 'z', '!' }, 1, 2));
283   }
284 
testPackagePrivateConstructor()285   private static void testPackagePrivateConstructor() {
286     try {
287       Class<?> c = Class.forName("sub.PPClass");
288       Constructor<?> cons = c.getConstructor();
289       cons.newInstance();
290       throw new RuntimeException("Expected IllegalAccessException.");
291     } catch (IllegalAccessException e) {
292       // Expected.
293     } catch (Exception e) {
294       // Error.
295       e.printStackTrace(System.out);
296     }
297   }
298 
testPackagePrivateAccessibleConstructor()299   private static void testPackagePrivateAccessibleConstructor() {
300     try {
301       Class<?> c = Class.forName("sub.PPClass");
302       Constructor<?> cons = c.getConstructor();
303       cons.setAccessible(true);  // ensure we prevent IllegalAccessException
304       cons.newInstance();
305     } catch (Exception e) {
306       // Error.
307       e.printStackTrace(System.out);
308     }
309   }
310 
testReflectFieldSetDuringClinit()311   private static void testReflectFieldSetDuringClinit() {
312     try {
313       int value = ReflectFieldSetDuringClinit.intField;
314       int expected = 42;
315       if (value != expected) {
316         System.out.println("Unexpected value: " + value + ", expected: " + expected);
317       }
318     } catch (Exception e) {
319       // Error.
320       e.printStackTrace(System.out);
321     }
322   }
323 
testReflectNewInstanceDuringClinit()324   private static void testReflectNewInstanceDuringClinit() {
325     try {
326       int value = ReflectNewInstanceDuringClinit.instance.intField;
327       int expected = 42;
328       if (value != expected) {
329         System.out.println("Unexpected value: " + value + ", expected: " + expected);
330       }
331     } catch (Exception e) {
332       // Error.
333       e.printStackTrace(System.out);
334     }
335   }
336 
main(String[] args)337   public static void main(String[] args) throws Exception {
338     testFieldReflection();
339     testMethodReflection();
340     testConstructorReflection();
341     testPackagePrivateConstructor();
342     testPackagePrivateAccessibleConstructor();
343     testReflectFieldSetDuringClinit();
344     testReflectNewInstanceDuringClinit();
345   }
346 }
347 
348 class ReflectFieldSetDuringClinit {
349   public static int intField;
350 
351   static {
352     try {
353       Field f = ReflectFieldSetDuringClinit.class.getDeclaredField("intField");
f.setInt(null, 42)354       f.setInt(null, 42);
355     } catch (Exception e) {
356       // Error.
357       e.printStackTrace(System.out);
358     }
359   }
360 }
361 
362 class ReflectNewInstanceDuringClinit {
363   public int intField;
364 
ReflectNewInstanceDuringClinit()365   public ReflectNewInstanceDuringClinit() {
366     intField = 42;
367   }
368 
369   public static ReflectNewInstanceDuringClinit instance;
370 
371   static {
372     try {
373       Constructor<?> ctor = ReflectNewInstanceDuringClinit.class.getConstructor();
374       instance = (ReflectNewInstanceDuringClinit) ctor.newInstance();
375     } catch (Exception e) {
376       // Error.
377       e.printStackTrace(System.out);
378     }
379   }
380 }
381