xref: /aosp_15_r20/art/test/064-field-access/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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 import other.PublicClass;
18 import java.lang.reflect.Field;
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21 
22 /*
23  * Test field access through reflection.
24  */
25 public class Main {
main(String[] args)26   public static void main(String[] args) {
27     System.loadLibrary(args[0]);
28 
29     SubClass.main(null);
30 
31     try {
32       GetNonexistent.main(null);
33       System.out.println("Not expected to succeed");
34     } catch (VerifyError fe) {
35       // dalvik
36       System.out.println("Got expected failure");
37     } catch (NoSuchFieldError nsfe) {
38       // reference
39       System.out.println("Got expected failure");
40     }
41 
42     try {
43       Class<?> c = Class.forName("SubClassUsingInaccessibleField");
44       Object o = c.newInstance();
45       c.getMethod("test").invoke(o, null);
46     } catch (InvocationTargetException ite) {
47       if (ite.getCause() instanceof IllegalAccessError) {
48         System.out.println("Got expected failure");
49       } else {
50         System.out.println("Got unexpected failure " + ite.getCause());
51       }
52     } catch (Exception e) {
53       System.out.println("Got unexpected failure " + e);
54     }
55 
56     try {
57       new GetInstanceFieldOnUninitializedThis();
58       // We actually allow this for app compat.
59       // System.out.println("Unexpectedly constructed GetInstanceFieldOnUninitializedThis");
60       System.out.println("GetInstanceFieldOnUninitializedThis allowed for app compat");
61     } catch (VerifyError expected) {
62       System.out.println("Got the correct but unexpected failure (should allow for app compat)");
63     } catch (Exception e) {
64       System.out.println("Got unexpected failure " + e);
65     }
66 
67     try {
68       new PutInstanceFieldOnUninitializedThisViaSubClass();
69       System.out.println("Unexpectedly constructed PutInstanceFieldOnUninitializedThisViaSubClass");
70     } catch (VerifyError expected) {
71       System.out.println("Got expected failure");
72     } catch (Exception e) {
73       System.out.println("Got unexpected failure " + e);
74     }
75 
76     OOMEOnNullAccess.main(args);
77   }
78 
79   /*
80    * Get the field specified by "field" from "obj".
81    *
82    * "type" determines which "get" call is made, e.g. 'B' turns into
83    * field.getByte().
84    *
85    * The "expectedException" must match the class of the exception thrown,
86    * or be null if no exception was expected.
87    *
88    * On success, the boxed value retrieved is returned.
89    */
getValue(Field field, Object obj, char type, Class<?> expectedException)90   public Object getValue(Field field, Object obj, char type,
91       Class<?> expectedException) {
92     Object result = null;
93     try {
94       switch (type) {
95         case 'Z':
96           result = field.getBoolean(obj);
97           break;
98         case 'B':
99           result = field.getByte(obj);
100           break;
101         case 'S':
102           result = field.getShort(obj);
103           break;
104         case 'C':
105           result = field.getChar(obj);
106           break;
107         case 'I':
108           result = field.getInt(obj);
109           break;
110         case 'J':
111           result = field.getLong(obj);
112           break;
113         case 'F':
114           result = field.getFloat(obj);
115           break;
116         case 'D':
117           result = field.getDouble(obj);
118           break;
119         case 'L':
120           result = field.get(obj);
121           break;
122         default:
123           throw new RuntimeException("bad type '" + type + "'");
124       }
125 
126       /* success; expected? */
127       if (expectedException != null) {
128         System.out.println("ERROR: call succeeded for field " + field +
129             " with a read of type '" + type +
130             "', was expecting " + expectedException);
131         Thread.dumpStack();
132       }
133     } catch (Exception ex) {
134       if (expectedException == null) {
135         System.out.println("ERROR: call failed unexpectedly: "
136             + ex.getClass());
137         ex.printStackTrace(System.out);
138       } else {
139         if (!expectedException.equals(ex.getClass())) {
140           System.out.println("ERROR: incorrect exception: wanted "
141               + expectedException.getName() + ", got "
142               + ex.getClass());
143           ex.printStackTrace(System.out);
144         }
145       }
146     }
147 
148     return result;
149   }
150 
startJit()151   static native void startJit();
stopJit()152   static native void stopJit();
waitForCompilation()153   static native void waitForCompilation();
154 }
155 
156 /*
157  * Local class with some fields.
158  */
159 class SamePackage {
160   public boolean samePackagePublicBooleanInstanceField = true;
161   public byte samePackagePublicByteInstanceField = 2;
162   public char samePackagePublicCharInstanceField = 3;
163   public short samePackagePublicShortInstanceField = 4;
164   public int samePackagePublicIntInstanceField = 5;
165   public long samePackagePublicLongInstanceField = 6;
166   public float samePackagePublicFloatInstanceField = 7.0f;
167   public double samePackagePublicDoubleInstanceField = 8.0;
168   public Object samePackagePublicObjectInstanceField = "9";
169 
170   protected boolean samePackageProtectedBooleanInstanceField = true;
171   protected byte samePackageProtectedByteInstanceField = 10;
172   protected char samePackageProtectedCharInstanceField = 11;
173   protected short samePackageProtectedShortInstanceField = 12;
174   protected int samePackageProtectedIntInstanceField = 13;
175   protected long samePackageProtectedLongInstanceField = 14;
176   protected float samePackageProtectedFloatInstanceField = 15.0f;
177   protected double samePackageProtectedDoubleInstanceField = 16.0;
178   protected Object samePackageProtectedObjectInstanceField = "17";
179 
180   private boolean samePackagePrivateBooleanInstanceField = true;
181   private byte samePackagePrivateByteInstanceField = 18;
182   private char samePackagePrivateCharInstanceField = 19;
183   private short samePackagePrivateShortInstanceField = 20;
184   private int samePackagePrivateIntInstanceField = 21;
185   private long samePackagePrivateLongInstanceField = 22;
186   private float samePackagePrivateFloatInstanceField = 23.0f;
187   private double samePackagePrivateDoubleInstanceField = 24.0;
188   private Object samePackagePrivateObjectInstanceField = "25";
189 
190   /* package */ boolean samePackagePackageBooleanInstanceField = true;
191   /* package */ byte samePackagePackageByteInstanceField = 26;
192   /* package */ char samePackagePackageCharInstanceField = 27;
193   /* package */ short samePackagePackageShortInstanceField = 28;
194   /* package */ int samePackagePackageIntInstanceField = 29;
195   /* package */ long samePackagePackageLongInstanceField = 30;
196   /* package */ float samePackagePackageFloatInstanceField = 31.0f;
197   /* package */ double samePackagePackageDoubleInstanceField = 32.0;
198   /* package */ Object samePackagePackageObjectInstanceField = "33";
199 
200   public static boolean samePackagePublicBooleanStaticField = true;
201   public static byte samePackagePublicByteStaticField = 34;
202   public static char samePackagePublicCharStaticField = 35;
203   public static short samePackagePublicShortStaticField = 36;
204   public static int samePackagePublicIntStaticField = 37;
205   public static long samePackagePublicLongStaticField = 38;
206   public static float samePackagePublicFloatStaticField = 39.0f;
207   public static double samePackagePublicDoubleStaticField = 40.0;
208   public static Object samePackagePublicObjectStaticField = "41";
209 
210   protected static boolean samePackageProtectedBooleanStaticField = true;
211   protected static byte samePackageProtectedByteStaticField = 42;
212   protected static char samePackageProtectedCharStaticField = 43;
213   protected static short samePackageProtectedShortStaticField = 44;
214   protected static int samePackageProtectedIntStaticField = 45;
215   protected static long samePackageProtectedLongStaticField = 46;
216   protected static float samePackageProtectedFloatStaticField = 47.0f;
217   protected static double samePackageProtectedDoubleStaticField = 48.0;
218   protected static Object samePackageProtectedObjectStaticField = "49";
219 
220   private static boolean samePackagePrivateBooleanStaticField = true;
221   private static byte samePackagePrivateByteStaticField = 50;
222   private static char samePackagePrivateCharStaticField = 51;
223   private static short samePackagePrivateShortStaticField = 52;
224   private static int samePackagePrivateIntStaticField = 53;
225   private static long samePackagePrivateLongStaticField = 54;
226   private static float samePackagePrivateFloatStaticField = 55.0f;
227   private static double samePackagePrivateDoubleStaticField = 56.0;
228   private static Object samePackagePrivateObjectStaticField = "57";
229 
230   /* package */ static boolean samePackagePackageBooleanStaticField = true;
231   /* package */ static byte samePackagePackageByteStaticField = 58;
232   /* package */ static char samePackagePackageCharStaticField = 59;
233   /* package */ static short samePackagePackageShortStaticField = 60;
234   /* package */ static int samePackagePackageIntStaticField = 61;
235   /* package */ static long samePackagePackageLongStaticField = 62;
236   /* package */ static float samePackagePackageFloatStaticField = 63.0f;
237   /* package */ static double samePackagePackageDoubleStaticField = 64.0;
238   /* package */ static Object samePackagePackageObjectStaticField = "65";
239 
samePublicMethod()240   public void samePublicMethod() { }
sameProtectedMethod()241   protected void sameProtectedMethod() { }
samePrivateMethod()242   private void samePrivateMethod() { }
samePackageMethod()243   /* package */ void samePackageMethod() { }
244 }
245 
246 /*
247  * This is a sub-class of other.PublicClass, which should be allowed to access
248  * the various protected fields declared by other.PublicClass and its parent
249  * other.ProtectedClass.
250  */
251 class SubClass extends PublicClass {
252   /*
253    * Perform the various tests.
254    *
255    * localInst.getValue() is performed using an instance of Main as the
256    * source of the reflection call.  otherInst.getValue() uses a subclass
257    * of OtherPackage as the source.
258    */
main(String[] args)259   public static void main(String[] args) {
260     SubClass subOther = new SubClass();
261     subOther.doDirectTests();
262     subOther.doReflectionTests();
263   }
264 
check(boolean b)265   private static void check(boolean b) {
266     if (!b) {
267       throw new Error("Test failed");
268     }
269   }
270 
doDirectTests()271   public void doDirectTests() {
272     check(otherProtectedClassPublicBooleanInstanceField == true);
273     check(otherProtectedClassPublicByteInstanceField == 2);
274     check(otherProtectedClassPublicCharInstanceField == 3);
275     check(otherProtectedClassPublicShortInstanceField == 4);
276     check(otherProtectedClassPublicIntInstanceField == 5);
277     check(otherProtectedClassPublicLongInstanceField == 6);
278     check(otherProtectedClassPublicFloatInstanceField == 7.0f);
279     check(otherProtectedClassPublicDoubleInstanceField == 8.0);
280     check(otherProtectedClassPublicObjectInstanceField == "9");
281 
282     check(otherProtectedClassProtectedBooleanInstanceField == true);
283     check(otherProtectedClassProtectedByteInstanceField == 10);
284     check(otherProtectedClassProtectedCharInstanceField == 11);
285     check(otherProtectedClassProtectedShortInstanceField == 12);
286     check(otherProtectedClassProtectedIntInstanceField == 13);
287     check(otherProtectedClassProtectedLongInstanceField == 14);
288     check(otherProtectedClassProtectedFloatInstanceField == 15.0f);
289     check(otherProtectedClassProtectedDoubleInstanceField == 16.0);
290     check(otherProtectedClassProtectedObjectInstanceField == "17");
291 
292     // check(otherProtectedClassPrivateBooleanInstanceField == true);
293     // check(otherProtectedClassPrivateByteInstanceField == 18);
294     // check(otherProtectedClassPrivateCharInstanceField == 19);
295     // check(otherProtectedClassPrivateShortInstanceField == 20);
296     // check(otherProtectedClassPrivateIntInstanceField == 21);
297     // check(otherProtectedClassPrivateLongInstanceField == 22);
298     // check(otherProtectedClassPrivateFloatInstanceField == 23.0f);
299     // check(otherProtectedClassPrivateDoubleInstanceField == 24.0);
300     // check(otherProtectedClassPrivateObjectInstanceField == "25");
301 
302     // check(otherProtectedClassPackageBooleanInstanceField == true);
303     // check(otherProtectedClassPackageByteInstanceField == 26);
304     // check(otherProtectedClassPackageCharInstanceField == 27);
305     // check(otherProtectedClassPackageShortInstanceField == 28);
306     // check(otherProtectedClassPackageIntInstanceField == 29);
307     // check(otherProtectedClassPackageLongInstanceField == 30);
308     // check(otherProtectedClassPackageFloatInstanceField == 31.0f);
309     // check(otherProtectedClassPackageDoubleInstanceField == 32.0);
310     // check(otherProtectedClassPackageObjectInstanceField == "33");
311 
312     check(otherProtectedClassPublicBooleanStaticField == true);
313     check(otherProtectedClassPublicByteStaticField == 34);
314     check(otherProtectedClassPublicCharStaticField == 35);
315     check(otherProtectedClassPublicShortStaticField == 36);
316     check(otherProtectedClassPublicIntStaticField == 37);
317     check(otherProtectedClassPublicLongStaticField == 38);
318     check(otherProtectedClassPublicFloatStaticField == 39.0f);
319     check(otherProtectedClassPublicDoubleStaticField == 40.0);
320     check(otherProtectedClassPublicObjectStaticField == "41");
321 
322     check(otherProtectedClassProtectedBooleanStaticField == true);
323     check(otherProtectedClassProtectedByteStaticField == 42);
324     check(otherProtectedClassProtectedCharStaticField == 43);
325     check(otherProtectedClassProtectedShortStaticField == 44);
326     check(otherProtectedClassProtectedIntStaticField == 45);
327     check(otherProtectedClassProtectedLongStaticField == 46);
328     check(otherProtectedClassProtectedFloatStaticField == 47.0f);
329     check(otherProtectedClassProtectedDoubleStaticField == 48.0);
330     check(otherProtectedClassProtectedObjectStaticField == "49");
331 
332     // check(otherProtectedClassPrivateBooleanStaticField == true);
333     // check(otherProtectedClassPrivateByteStaticField == 50);
334     // check(otherProtectedClassPrivateCharStaticField == 51);
335     // check(otherProtectedClassPrivateShortStaticField == 52);
336     // check(otherProtectedClassPrivateIntStaticField == 53);
337     // check(otherProtectedClassPrivateLongStaticField == 54);
338     // check(otherProtectedClassPrivateFloatStaticField == 55.0f);
339     // check(otherProtectedClassPrivateDoubleStaticField == 56.0);
340     // check(otherProtectedClassPrivateObjectStaticField == "57");
341 
342     // check(otherProtectedClassPackageBooleanStaticField == true);
343     // check(otherProtectedClassPackageByteStaticField == 58);
344     // check(otherProtectedClassPackageCharStaticField == 59);
345     // check(otherProtectedClassPackageShortStaticField == 60);
346     // check(otherProtectedClassPackageIntStaticField == 61);
347     // check(otherProtectedClassPackageLongStaticField == 62);
348     // check(otherProtectedClassPackageFloatStaticField == 63.0f);
349     // check(otherProtectedClassPackageDoubleStaticField == 64.0);
350     // check(otherProtectedClassPackageObjectStaticField == "65");
351 
352     check(otherPublicClassPublicBooleanInstanceField == true);
353     check(otherPublicClassPublicByteInstanceField == -2);
354     check(otherPublicClassPublicCharInstanceField == (char)-3);
355     check(otherPublicClassPublicShortInstanceField == -4);
356     check(otherPublicClassPublicIntInstanceField == -5);
357     check(otherPublicClassPublicLongInstanceField == -6);
358     check(otherPublicClassPublicFloatInstanceField == -7.0f);
359     check(otherPublicClassPublicDoubleInstanceField == -8.0);
360     check(otherPublicClassPublicObjectInstanceField == "-9");
361 
362     check(otherPublicClassProtectedBooleanInstanceField == true);
363     check(otherPublicClassProtectedByteInstanceField == -10);
364     check(otherPublicClassProtectedCharInstanceField == (char)-11);
365     check(otherPublicClassProtectedShortInstanceField == -12);
366     check(otherPublicClassProtectedIntInstanceField == -13);
367     check(otherPublicClassProtectedLongInstanceField == -14);
368     check(otherPublicClassProtectedFloatInstanceField == -15.0f);
369     check(otherPublicClassProtectedDoubleInstanceField == -16.0);
370     check(otherPublicClassProtectedObjectInstanceField == "-17");
371 
372     // check(otherPublicClassPrivateBooleanInstanceField == true);
373     // check(otherPublicClassPrivateByteInstanceField == -18);
374     // check(otherPublicClassPrivateCharInstanceField == (char)-19);
375     // check(otherPublicClassPrivateShortInstanceField == -20);
376     // check(otherPublicClassPrivateIntInstanceField == -21);
377     // check(otherPublicClassPrivateLongInstanceField == -22);
378     // check(otherPublicClassPrivateFloatInstanceField == -23.0f);
379     // check(otherPublicClassPrivateDoubleInstanceField == -24.0);
380     // check(otherPublicClassPrivateObjectInstanceField == "-25");
381 
382     // check(otherPublicClassPackageBooleanInstanceField == true);
383     // check(otherPublicClassPackageByteInstanceField == -26);
384     // check(otherPublicClassPackageCharInstanceField == (char)-27);
385     // check(otherPublicClassPackageShortInstanceField == -28);
386     // check(otherPublicClassPackageIntInstanceField == -29);
387     // check(otherPublicClassPackageLongInstanceField == -30);
388     // check(otherPublicClassPackageFloatInstanceField == -31.0f);
389     // check(otherPublicClassPackageDoubleInstanceField == -32.0);
390     // check(otherPublicClassPackageObjectInstanceField == "-33");
391 
392     check(otherPublicClassPublicBooleanStaticField == true);
393     check(otherPublicClassPublicByteStaticField == -34);
394     check(otherPublicClassPublicCharStaticField == (char)-35);
395     check(otherPublicClassPublicShortStaticField == -36);
396     check(otherPublicClassPublicIntStaticField == -37);
397     check(otherPublicClassPublicLongStaticField == -38);
398     check(otherPublicClassPublicFloatStaticField == -39.0f);
399     check(otherPublicClassPublicDoubleStaticField == -40.0);
400     check(otherPublicClassPublicObjectStaticField == "-41");
401 
402     check(otherPublicClassProtectedBooleanStaticField == true);
403     check(otherPublicClassProtectedByteStaticField == -42);
404     check(otherPublicClassProtectedCharStaticField == (char)-43);
405     check(otherPublicClassProtectedShortStaticField == -44);
406     check(otherPublicClassProtectedIntStaticField == -45);
407     check(otherPublicClassProtectedLongStaticField == -46);
408     check(otherPublicClassProtectedFloatStaticField == -47.0f);
409     check(otherPublicClassProtectedDoubleStaticField == -48.0);
410     check(otherPublicClassProtectedObjectStaticField == "-49");
411 
412     // check(otherPublicClassPrivateBooleanStaticField == true);
413     // check(otherPublicClassPrivateByteStaticField == -50);
414     // check(otherPublicClassPrivateCharStaticField == (char)-51);
415     // check(otherPublicClassPrivateShortStaticField == -52);
416     // check(otherPublicClassPrivateIntStaticField == -53);
417     // check(otherPublicClassPrivateLongStaticField == -54);
418     // check(otherPublicClassPrivateFloatStaticField == -55.0f);
419     // check(otherPublicClassPrivateDoubleStaticField == -56.0);
420     // check(otherPublicClassPrivateObjectStaticField == "-57");
421 
422     // check(otherPublicClassPackageBooleanStaticField == true);
423     // check(otherPublicClassPackageByteStaticField == -58);
424     // check(otherPublicClassPackageCharStaticField == (char)-59);
425     // check(otherPublicClassPackageShortStaticField == -60);
426     // check(otherPublicClassPackageIntStaticField == -61);
427     // check(otherPublicClassPackageLongStaticField == -62);
428     // check(otherPublicClassPackageFloatStaticField == -63.0f);
429     // check(otherPublicClassPackageDoubleStaticField == -64.0);
430     // check(otherPublicClassPackageObjectStaticField == "-65");
431 
432     SamePackage s = new SamePackage();
433     check(s.samePackagePublicBooleanInstanceField == true);
434     check(s.samePackagePublicByteInstanceField == 2);
435     check(s.samePackagePublicCharInstanceField == 3);
436     check(s.samePackagePublicShortInstanceField == 4);
437     check(s.samePackagePublicIntInstanceField == 5);
438     check(s.samePackagePublicLongInstanceField == 6);
439     check(s.samePackagePublicFloatInstanceField == 7.0f);
440     check(s.samePackagePublicDoubleInstanceField == 8.0);
441     check(s.samePackagePublicObjectInstanceField == "9");
442 
443     check(s.samePackageProtectedBooleanInstanceField == true);
444     check(s.samePackageProtectedByteInstanceField == 10);
445     check(s.samePackageProtectedCharInstanceField == 11);
446     check(s.samePackageProtectedShortInstanceField == 12);
447     check(s.samePackageProtectedIntInstanceField == 13);
448     check(s.samePackageProtectedLongInstanceField == 14);
449     check(s.samePackageProtectedFloatInstanceField == 15.0f);
450     check(s.samePackageProtectedDoubleInstanceField == 16.0);
451     check(s.samePackageProtectedObjectInstanceField == "17");
452 
453     // check(s.samePackagePrivateBooleanInstanceField == true);
454     // check(s.samePackagePrivateByteInstanceField == 18);
455     // check(s.samePackagePrivateCharInstanceField == 19);
456     // check(s.samePackagePrivateShortInstanceField == 20);
457     // check(s.samePackagePrivateIntInstanceField == 21);
458     // check(s.samePackagePrivateLongInstanceField == 22);
459     // check(s.samePackagePrivateFloatInstanceField == 23.0f);
460     // check(s.samePackagePrivateDoubleInstanceField == 24.0);
461     // check(s.samePackagePrivateObjectInstanceField == "25");
462 
463     check(s.samePackagePackageBooleanInstanceField == true);
464     check(s.samePackagePackageByteInstanceField == 26);
465     check(s.samePackagePackageCharInstanceField == 27);
466     check(s.samePackagePackageShortInstanceField == 28);
467     check(s.samePackagePackageIntInstanceField == 29);
468     check(s.samePackagePackageLongInstanceField == 30);
469     check(s.samePackagePackageFloatInstanceField == 31.0f);
470     check(s.samePackagePackageDoubleInstanceField == 32.0);
471     check(s.samePackagePackageObjectInstanceField == "33");
472 
473     check(SamePackage.samePackagePublicBooleanStaticField == true);
474     check(SamePackage.samePackagePublicByteStaticField == 34);
475     check(SamePackage.samePackagePublicCharStaticField == 35);
476     check(SamePackage.samePackagePublicShortStaticField == 36);
477     check(SamePackage.samePackagePublicIntStaticField == 37);
478     check(SamePackage.samePackagePublicLongStaticField == 38);
479     check(SamePackage.samePackagePublicFloatStaticField == 39.0f);
480     check(SamePackage.samePackagePublicDoubleStaticField == 40.0);
481     check(SamePackage.samePackagePublicObjectStaticField == "41");
482 
483     check(SamePackage.samePackageProtectedBooleanStaticField == true);
484     check(SamePackage.samePackageProtectedByteStaticField == 42);
485     check(SamePackage.samePackageProtectedCharStaticField == 43);
486     check(SamePackage.samePackageProtectedShortStaticField == 44);
487     check(SamePackage.samePackageProtectedIntStaticField == 45);
488     check(SamePackage.samePackageProtectedLongStaticField == 46);
489     check(SamePackage.samePackageProtectedFloatStaticField == 47.0f);
490     check(SamePackage.samePackageProtectedDoubleStaticField == 48.0);
491     check(SamePackage.samePackageProtectedObjectStaticField == "49");
492 
493     // check(SamePackage.samePackagePrivateBooleanStaticField == true);
494     // check(SamePackage.samePackagePrivateByteStaticField == 50);
495     // check(SamePackage.samePackagePrivateCharStaticField == 51);
496     // check(SamePackage.samePackagePrivateShortStaticField == 52);
497     // check(SamePackage.samePackagePrivateIntStaticField == 53);
498     // check(SamePackage.samePackagePrivateLongStaticField == 54);
499     // check(SamePackage.samePackagePrivateFloatStaticField == 55.0f);
500     // check(SamePackage.samePackagePrivateDoubleStaticField == 56.0);
501     // check(SamePackage.samePackagePrivateObjectStaticField == "57");
502 
503     check(SamePackage.samePackagePackageBooleanStaticField == true);
504     check(SamePackage.samePackagePackageByteStaticField == 58);
505     check(SamePackage.samePackagePackageCharStaticField == 59);
506     check(SamePackage.samePackagePackageShortStaticField == 60);
507     check(SamePackage.samePackagePackageIntStaticField == 61);
508     check(SamePackage.samePackagePackageLongStaticField == 62);
509     check(SamePackage.samePackagePackageFloatStaticField == 63.0f);
510     check(SamePackage.samePackagePackageDoubleStaticField == 64.0);
511     check(SamePackage.samePackagePackageObjectStaticField == "65");
512   }
513 
compatibleTypes(char srcType, char dstType)514   private static boolean compatibleTypes(char srcType, char dstType) {
515     switch (dstType) {
516       case 'Z':
517       case 'C':
518       case 'B':
519         return srcType == dstType;
520       case 'S':
521         return srcType == 'B' || srcType == 'S';
522       case 'I':
523         return srcType == 'B' || srcType == 'C' || srcType == 'S' || srcType == 'I';
524       case 'J':
525         return srcType == 'B' || srcType == 'C' || srcType == 'S' || srcType == 'I' ||
526         srcType == 'J';
527       case 'F':
528         return srcType == 'B' || srcType == 'C' || srcType == 'S' || srcType == 'I' ||
529         srcType == 'J' || srcType == 'F';
530       case 'D':
531         return srcType == 'B' || srcType == 'C' || srcType == 'S' || srcType == 'I' ||
532         srcType == 'J' || srcType == 'F' || srcType == 'D';
533       case 'L':
534         return true;
535       default:
536         throw new Error("Unexpected type char " + dstType);
537     }
538   }
539 
doReflectionTests()540   public void doReflectionTests() {
541     String typeChars = "ZBCSIJFDL";
542     String fieldNameForTypeChar[] = {
543         "Boolean",
544         "Byte",
545         "Char",
546         "Short",
547         "Int",
548         "Long",
549         "Float",
550         "Double",
551         "Object"
552     };
553 
554     Main localInst = new Main();
555     SamePackage samePkgInst = new SamePackage();
556     PublicClass otherPkgInst = new PublicClass();
557     Object plainObj = new Object();
558 
559     for (int round = 0; round < 3; round++) {
560       Object validInst;
561       Field[] fields;
562       Method[] methods;
563       boolean same_package = false;
564       boolean protected_class = false;
565       switch (round) {
566         case 0:
567           validInst = new SamePackage();
568           fields = SamePackage.class.getDeclaredFields();
569           check(fields.length == 72);
570           methods = SamePackage.class.getDeclaredMethods();
571           check(methods.length == 4);
572           same_package = true;
573           break;
574         case 1:
575           validInst = new PublicClass();
576           fields = PublicClass.class.getDeclaredFields();
577           check(fields.length == 72);
578           methods = PublicClass.class.getDeclaredMethods();
579           check(methods.length == 4);
580           break;
581         default:
582           validInst = new PublicClass();
583           fields = PublicClass.class.getSuperclass().getDeclaredFields();
584           check(fields.length == 72);
585           methods = PublicClass.class.getSuperclass().getDeclaredMethods();
586           check(methods.length == 4);
587           protected_class = true;
588           break;
589       }
590       for (Field f : fields) {
591         char typeChar = '?';
592         for (int i = 0; i < fieldNameForTypeChar.length; i++) {
593           if (f.getName().contains(fieldNameForTypeChar[i])) {
594             typeChar = typeChars.charAt(i);
595             break;
596           }
597         }
598         // Check access or lack of to field.
599         Class<?> subClassAccessExceptionClass = null;
600         if ((f.getName().contains("Private") ||
601             (!same_package && f.getName().contains("Package")) ||
602             (!same_package && f.getName().contains("Protected"))) &&
603             !(protected_class && f.getName().contains("Public"))) {
604           subClassAccessExceptionClass = IllegalAccessException.class;
605         }
606         Class<?> mainClassAccessExceptionClass = null;
607         if ((f.getName().contains("Private") ||
608             (!same_package && f.getName().contains("Package")) ||
609             (!same_package && f.getName().contains("Protected"))) &&
610             !(protected_class && f.getName().contains("Public"))) {
611           mainClassAccessExceptionClass = IllegalAccessException.class;
612         }
613 
614         this.getValue(f, validInst, typeChar, subClassAccessExceptionClass);
615         localInst.getValue(f, validInst, typeChar, mainClassAccessExceptionClass);
616 
617         // Check things that can get beyond the IllegalAccessException.
618         if (subClassAccessExceptionClass == null) {
619           // Check NPE.
620           Class<?> npeClass = null;
621           if (!f.getName().contains("Static")) {
622             npeClass = NullPointerException.class;
623           }
624 
625           this.getValue(f, null, typeChar, npeClass);
626           if (mainClassAccessExceptionClass == null) {
627             localInst.getValue(f, null, typeChar, npeClass);
628           }
629 
630           // Check access of wrong field type for valid instance.
631           for (int i = 0; i < typeChars.length(); i++) {
632             char otherChar = typeChars.charAt(i);
633             Class<?> illArgClass = compatibleTypes(typeChar, otherChar) ?
634                 null : IllegalArgumentException.class;
635             this.getValue(f, validInst, otherChar, illArgClass);
636             if (mainClassAccessExceptionClass == null) {
637               localInst.getValue(f, validInst, otherChar, illArgClass);
638             }
639           }
640 
641           if (!f.getName().contains("Static")) {
642             // Wrong object.
643             this.getValue(f, plainObj, typeChar, IllegalArgumentException.class);
644             if (mainClassAccessExceptionClass == null) {
645               localInst.getValue(f, plainObj, typeChar, IllegalArgumentException.class);
646             }
647           }
648         }
649       }
650 
651       for (Method m : methods) {
652         Class<?> subClassAccessExceptionClass = null;
653         if (m.getName().contains("Private") ||
654             (!same_package && m.getName().contains("Package")) ||
655             (!same_package && m.getName().contains("Protected"))) {
656           subClassAccessExceptionClass = IllegalAccessException.class;
657         }
658         this.invoke(m, validInst, subClassAccessExceptionClass);
659       }
660     }
661     System.out.println("good");
662   }
663 
664   /*
665    * [this is a clone of Main.getValue() -- the class issuing the
666    * reflection call is significant]
667    */
getValue(Field field, Object obj, char type, Class<?> expectedException)668   public Object getValue(Field field, Object obj, char type,
669       Class<?> expectedException) {
670     Object result = null;
671     try {
672       switch (type) {
673         case 'Z':
674           result = field.getBoolean(obj);
675           break;
676         case 'B':
677           result = field.getByte(obj);
678           break;
679         case 'S':
680           result = field.getShort(obj);
681           break;
682         case 'C':
683           result = field.getChar(obj);
684           break;
685         case 'I':
686           result = field.getInt(obj);
687           break;
688         case 'J':
689           result = field.getLong(obj);
690           break;
691         case 'F':
692           result = field.getFloat(obj);
693           break;
694         case 'D':
695           result = field.getDouble(obj);
696           break;
697         case 'L':
698           result = field.get(obj);
699           break;
700         default:
701           throw new RuntimeException("bad type '" + type + "'");
702       }
703 
704       /* success; expected? */
705       if (expectedException != null) {
706         System.out.println("ERROR: call succeeded for field " + field +
707             " with a read of type '" + type +
708             "', was expecting " + expectedException);
709         Thread.dumpStack();
710       }
711     } catch (Exception ex) {
712       if (expectedException == null) {
713         System.out.println("ERROR: call failed unexpectedly: "
714             + ex.getClass());
715         ex.printStackTrace(System.out);
716       } else {
717         if (!expectedException.equals(ex.getClass())) {
718           System.out.println("ERROR: incorrect exception: wanted "
719               + expectedException.getName() + ", got "
720               + ex.getClass());
721           ex.printStackTrace(System.out);
722         }
723       }
724     }
725 
726     return result;
727   }
728 
invoke(Method method, Object obj, Class<?> expectedException)729   public Object invoke(Method method, Object obj, Class<?> expectedException) {
730     Object result = null;
731     try {
732       result = method.invoke(obj);
733       /* success; expected? */
734       if (expectedException != null) {
735         System.out.println("ERROR: call succeeded for method " + method + "', was expecting " +
736                            expectedException);
737         Thread.dumpStack();
738       }
739     } catch (Exception ex) {
740       if (expectedException == null) {
741         System.out.println("ERROR: call failed unexpectedly: " + ex.getClass());
742         ex.printStackTrace(System.out);
743       } else {
744         if (!expectedException.equals(ex.getClass())) {
745           System.out.println("ERROR: incorrect exception: wanted " + expectedException.getName() +
746                              ", got " + ex.getClass());
747           ex.printStackTrace(System.out);
748         }
749       }
750     }
751     return result;
752   }
753 }
754