1 /*
2  * Copyright (C) 2016 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 import java.lang.invoke.MethodHandle;
17 import java.lang.invoke.MethodHandles;
18 import java.lang.invoke.WrongMethodTypeException;
19 import java.lang.reflect.Field;
20 
21 public class Main {
22 
23     public static class ValueHolder {
24         public boolean m_z = false;
25         public byte m_b = 0;
26         public char m_c = 'a';
27         public short m_s = 0;
28         public int m_i = 0;
29         public float m_f = 0.0f;
30         public double m_d = 0.0;
31         public long m_j = 0;
32         public String m_l = "a";
33 
34         public static boolean s_z;
35         public static byte s_b;
36         public static char s_c;
37         public static short s_s;
38         public static int s_i;
39         public static float s_f;
40         public static double s_d;
41         public static long s_j;
42         public static String s_l;
43 
44         public final int m_fi = 0xa5a5a5a5;
45         public static final int s_fi = 0x5a5a5a5a;
46 
47         private boolean m_pz;
48         private static final boolean s_fz = false;
49     }
50 
51     public static class Tester {
assertEquals(boolean expected, boolean actual)52         public static void assertEquals(boolean expected, boolean actual) {
53             if (actual != expected) {
54                 throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")");
55             }
56         }
57 
assertEquals(char expected, char actual)58         public static void assertEquals(char expected, char actual) {
59             if (actual != expected) {
60                 throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")");
61             }
62         }
63 
assertEquals(int expected, int actual)64         public static void assertEquals(int expected, int actual) {
65             if (actual != expected) {
66                 throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")");
67             }
68         }
69 
assertTrue(boolean value)70         public static void assertTrue(boolean value) throws AssertionError {
71             if (!value) {
72                 throw new AssertionError("Value is not true");
73             }
74         }
75 
fail()76         public static void fail() throws Throwable{
77             throw new Error("fail");
78         }
79     }
80 
81     public static class InvokeExactTester extends Tester {
82         private enum PrimitiveType {
83             Boolean,
84             Byte,
85             Char,
86             Short,
87             Int,
88             Long,
89             Float,
90             Double,
91             String,
92         }
93 
94         private enum AccessorType {
95             IPUT,
96             SPUT,
97             IGET,
98             SGET,
99         }
100 
setByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure)101         static void setByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure)
102                 throws Throwable {
103             boolean exceptionThrown = false;
104             try {
105                 if (v == null) {
106                     m.invokeExact(value);
107                 }
108                 else {
109                     m.invokeExact(v, value);
110                 }
111             }
112             catch (WrongMethodTypeException e) {
113                 exceptionThrown = true;
114             }
115             assertEquals(expectFailure, exceptionThrown);
116         }
117 
setByte(MethodHandle m, byte value, boolean expectFailure)118         static void setByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable {
119             setByte(m, null, value, expectFailure);
120         }
121 
getByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure)122         static void getByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure)
123                 throws Throwable {
124             boolean exceptionThrown = false;
125             try {
126                 final byte got;
127                 if (v == null) {
128                     got = (byte) m.invokeExact();
129                 } else {
130                     got = (byte) m.invokeExact(v);
131                 }
132                 assertTrue(got == value);
133             }
134             catch (WrongMethodTypeException e) {
135                 exceptionThrown = true;
136             }
137             assertEquals(expectFailure, exceptionThrown);
138         }
139 
getByte(MethodHandle m, byte value, boolean expectFailure)140         static void getByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable {
141             getByte(m, null, value, expectFailure);
142         }
143 
setChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure)144         static void setChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure)
145                 throws Throwable {
146             boolean exceptionThrown = false;
147             try {
148                 if (v == null) {
149                     m.invokeExact(value);
150                 }
151                 else {
152                     m.invokeExact(v, value);
153                 }
154             }
155             catch (WrongMethodTypeException e) {
156                 exceptionThrown = true;
157             }
158             assertEquals(expectFailure, exceptionThrown);
159         }
160 
setChar(MethodHandle m, char value, boolean expectFailure)161         static void setChar(MethodHandle m, char value, boolean expectFailure) throws Throwable {
162             setChar(m, null, value, expectFailure);
163         }
164 
getChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure)165         static void getChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure)
166                 throws Throwable {
167             boolean exceptionThrown = false;
168             try {
169                 final char got;
170                 if (v == null) {
171                     got = (char) m.invokeExact();
172                 } else {
173                     got = (char) m.invokeExact(v);
174                 }
175                 assertTrue(got == value);
176             }
177             catch (WrongMethodTypeException e) {
178                 exceptionThrown = true;
179             }
180             assertEquals(expectFailure, exceptionThrown);
181         }
182 
getChar(MethodHandle m, char value, boolean expectFailure)183         static void getChar(MethodHandle m, char value, boolean expectFailure) throws Throwable {
184             getChar(m, null, value, expectFailure);
185         }
186 
setShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure)187         static void setShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure)
188                 throws Throwable {
189             boolean exceptionThrown = false;
190             try {
191                 if (v == null) {
192                     m.invokeExact(value);
193                 }
194                 else {
195                     m.invokeExact(v, value);
196                 }
197             }
198             catch (WrongMethodTypeException e) {
199                 exceptionThrown = true;
200             }
201             assertEquals(expectFailure, exceptionThrown);
202         }
203 
setShort(MethodHandle m, short value, boolean expectFailure)204         static void setShort(MethodHandle m, short value, boolean expectFailure) throws Throwable {
205             setShort(m, null, value, expectFailure);
206         }
207 
getShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure)208         static void getShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure)
209                 throws Throwable {
210             boolean exceptionThrown = false;
211             try {
212                 final short got = (v == null) ? (short) m.invokeExact() : (short) m.invokeExact(v);
213                 assertTrue(got == value);
214             }
215             catch (WrongMethodTypeException e) {
216                 exceptionThrown = true;
217             }
218             assertEquals(expectFailure, exceptionThrown);
219         }
220 
getShort(MethodHandle m, short value, boolean expectFailure)221         static void getShort(MethodHandle m, short value, boolean expectFailure) throws Throwable {
222             getShort(m, null, value, expectFailure);
223         }
224 
setInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure)225         static void setInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure)
226                 throws Throwable {
227             boolean exceptionThrown = false;
228             try {
229                 if (v == null) {
230                     m.invokeExact(value);
231                 }
232                 else {
233                     m.invokeExact(v, value);
234                 }
235             }
236             catch (WrongMethodTypeException e) {
237                 exceptionThrown = true;
238             }
239             assertEquals(expectFailure, exceptionThrown);
240         }
241 
setInt(MethodHandle m, int value, boolean expectFailure)242         static void setInt(MethodHandle m, int value, boolean expectFailure) throws Throwable {
243             setInt(m, null, value, expectFailure);
244         }
245 
getInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure)246         static void getInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure)
247                 throws Throwable {
248             boolean exceptionThrown = false;
249             try {
250                 final int got = (v == null) ? (int) m.invokeExact() : (int) m.invokeExact(v);
251                 assertTrue(got == value);
252             }
253             catch (WrongMethodTypeException e) {
254                 exceptionThrown = true;
255             }
256             assertEquals(expectFailure, exceptionThrown);
257         }
258 
getInt(MethodHandle m, int value, boolean expectFailure)259         static void getInt(MethodHandle m, int value, boolean expectFailure) throws Throwable {
260             getInt(m, null, value, expectFailure);
261         }
262 
setLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure)263         static void setLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure)
264                 throws Throwable {
265             boolean exceptionThrown = false;
266             try {
267                 if (v == null) {
268                     m.invokeExact(value);
269                 }
270                 else {
271                     m.invokeExact(v, value);
272                 }
273             }
274             catch (WrongMethodTypeException e) {
275                 exceptionThrown = true;
276             }
277             assertEquals(expectFailure, exceptionThrown);
278         }
279 
setLong(MethodHandle m, long value, boolean expectFailure)280         static void setLong(MethodHandle m, long value, boolean expectFailure) throws Throwable {
281             setLong(m, null, value, expectFailure);
282         }
283 
getLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure)284         static void getLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure)
285                 throws Throwable {
286             boolean exceptionThrown = false;
287             try {
288                 final long got = (v == null) ? (long) m.invokeExact() : (long) m.invokeExact(v);
289                 assertTrue(got == value);
290             }
291             catch (WrongMethodTypeException e) {
292                 exceptionThrown = true;
293             }
294             assertEquals(expectFailure, exceptionThrown);
295         }
296 
getLong(MethodHandle m, long value, boolean expectFailure)297         static void getLong(MethodHandle m, long value, boolean expectFailure) throws Throwable {
298             getLong(m, null, value, expectFailure);
299         }
300 
setFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure)301         static void setFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure)
302                 throws Throwable {
303             boolean exceptionThrown = false;
304             try {
305                 if (v == null) {
306                     m.invokeExact(value);
307                 }
308                 else {
309                     m.invokeExact(v, value);
310                 }
311             }
312             catch (WrongMethodTypeException e) {
313                 exceptionThrown = true;
314             }
315             assertEquals(expectFailure, exceptionThrown);
316         }
317 
setFloat(MethodHandle m, float value, boolean expectFailure)318         static void setFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable {
319             setFloat(m, null, value, expectFailure);
320         }
321 
getFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure)322         static void getFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure)
323                 throws Throwable {
324             boolean exceptionThrown = false;
325             try {
326                 final float got = (v == null) ? (float) m.invokeExact() : (float) m.invokeExact(v);
327                 assertTrue(got == value);
328             }
329             catch (WrongMethodTypeException e) {
330                 exceptionThrown = true;
331             }
332             assertEquals(expectFailure, exceptionThrown);
333         }
334 
getFloat(MethodHandle m, float value, boolean expectFailure)335         static void getFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable {
336             getFloat(m, null, value, expectFailure);
337         }
338 
setDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure)339         static void setDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure)
340                 throws Throwable {
341             boolean exceptionThrown = false;
342             try {
343                 if (v == null) {
344                     m.invokeExact(value);
345                 }
346                 else {
347                     m.invokeExact(v, value);
348                 }
349             }
350             catch (WrongMethodTypeException e) {
351                 exceptionThrown = true;
352             }
353             assertEquals(expectFailure, exceptionThrown);
354         }
355 
setDouble(MethodHandle m, double value, boolean expectFailure)356         static void setDouble(MethodHandle m, double value, boolean expectFailure)
357                 throws Throwable {
358             setDouble(m, null, value, expectFailure);
359         }
360 
getDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure)361         static void getDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure)
362                 throws Throwable {
363             boolean exceptionThrown = false;
364             try {
365                 final double got = (v == null) ? (double) m.invokeExact() : (double) m.invokeExact(v);
366                 assertTrue(got == value);
367             }
368             catch (WrongMethodTypeException e) {
369                 exceptionThrown = true;
370             }
371             assertEquals(expectFailure, exceptionThrown);
372         }
373 
getDouble(MethodHandle m, double value, boolean expectFailure)374         static void getDouble(MethodHandle m, double value, boolean expectFailure)
375                 throws Throwable {
376             getDouble(m, null, value, expectFailure);
377         }
378 
setString(MethodHandle m, ValueHolder v, String value, boolean expectFailure)379         static void setString(MethodHandle m, ValueHolder v, String value, boolean expectFailure)
380                 throws Throwable {
381             boolean exceptionThrown = false;
382             try {
383                 if (v == null) {
384                     m.invokeExact(value);
385                 }
386                 else {
387                     m.invokeExact(v, value);
388                 }
389             }
390             catch (WrongMethodTypeException e) {
391                 exceptionThrown = true;
392             }
393             assertEquals(expectFailure, exceptionThrown);
394         }
395 
setString(MethodHandle m, String value, boolean expectFailure)396         static void setString(MethodHandle m, String value, boolean expectFailure)
397                 throws Throwable {
398             setString(m, null, value, expectFailure);
399         }
400 
getString(MethodHandle m, ValueHolder v, String value, boolean expectFailure)401         static void getString(MethodHandle m, ValueHolder v, String value, boolean expectFailure)
402                 throws Throwable {
403             boolean exceptionThrown = false;
404             try {
405                 final String got = (v == null) ? (String) m.invokeExact() : (String) m.invokeExact(v);
406                 assertTrue(got.equals(value));
407             }
408             catch (WrongMethodTypeException e) {
409                 exceptionThrown = true;
410             }
411             assertEquals(expectFailure, exceptionThrown);
412         }
413 
getString(MethodHandle m, String value, boolean expectFailure)414         static void getString(MethodHandle m, String value, boolean expectFailure)
415                 throws Throwable {
416             getString(m, null, value, expectFailure);
417         }
418 
setBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure)419         static void setBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure)
420                 throws Throwable {
421             boolean exceptionThrown = false;
422             try {
423                 if (v == null) {
424                     m.invokeExact(value);
425                 }
426                 else {
427                     m.invokeExact(v, value);
428                 }
429             }
430             catch (WrongMethodTypeException e) {
431                 exceptionThrown = true;
432             }
433             assertEquals(expectFailure, exceptionThrown);
434         }
435 
setBoolean(MethodHandle m, boolean value, boolean expectFailure)436         static void setBoolean(MethodHandle m, boolean value, boolean expectFailure)
437                 throws Throwable {
438             setBoolean(m, null, value, expectFailure);
439         }
440 
getBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure)441         static void getBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure)
442                 throws Throwable {
443             boolean exceptionThrown = false;
444             try {
445                 final boolean got =
446                         (v == null) ? (boolean) m.invokeExact() : (boolean) m.invokeExact(v);
447                 assertTrue(got == value);
448             }
449             catch (WrongMethodTypeException e) {
450                 exceptionThrown = true;
451             }
452             assertEquals(expectFailure, exceptionThrown);
453         }
454 
getBoolean(MethodHandle m, boolean value, boolean expectFailure)455         static void getBoolean(MethodHandle m, boolean value, boolean expectFailure)
456                 throws Throwable {
457             getBoolean(m, null, value, expectFailure);
458         }
459 
resultFor(PrimitiveType actualType, PrimitiveType expectedType, AccessorType actualAccessor, AccessorType expectedAccessor)460         static boolean resultFor(PrimitiveType actualType, PrimitiveType expectedType,
461                                  AccessorType actualAccessor,
462                                  AccessorType expectedAccessor) {
463             return (actualType != expectedType) || (actualAccessor != expectedAccessor);
464         }
465 
tryAccessor(MethodHandle methodHandle, ValueHolder valueHolder, PrimitiveType primitive, Object value, AccessorType accessor)466         static void tryAccessor(MethodHandle methodHandle,
467                                 ValueHolder valueHolder,
468                                 PrimitiveType primitive,
469                                 Object value,
470                                 AccessorType accessor) throws Throwable {
471             boolean booleanValue =
472                     value instanceof Boolean ? ((Boolean) value).booleanValue() : false;
473             setBoolean(methodHandle, valueHolder, booleanValue,
474                        resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.IPUT));
475             setBoolean(methodHandle, booleanValue,
476                        resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.SPUT));
477             getBoolean(methodHandle, valueHolder, booleanValue,
478                        resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.IGET));
479             getBoolean(methodHandle, booleanValue,
480                        resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.SGET));
481 
482             byte byteValue = value instanceof Byte ? ((Byte) value).byteValue() : (byte) 0;
483             setByte(methodHandle, valueHolder, byteValue,
484                     resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.IPUT));
485             setByte(methodHandle, byteValue,
486                     resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.SPUT));
487             getByte(methodHandle, valueHolder, byteValue,
488                     resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.IGET));
489             getByte(methodHandle, byteValue,
490                     resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.SGET));
491 
492             char charValue = value instanceof Character ? ((Character) value).charValue() : 'z';
493             setChar(methodHandle, valueHolder, charValue,
494                     resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.IPUT));
495             setChar(methodHandle, charValue,
496                     resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.SPUT));
497             getChar(methodHandle, valueHolder, charValue,
498                     resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.IGET));
499             getChar(methodHandle, charValue,
500                     resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.SGET));
501 
502             short shortValue = value instanceof Short ? ((Short) value).shortValue() : (short) 0;
503             setShort(methodHandle, valueHolder, shortValue,
504                      resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.IPUT));
505             setShort(methodHandle, shortValue,
506                     resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.SPUT));
507             getShort(methodHandle, valueHolder, shortValue,
508                      resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.IGET));
509             getShort(methodHandle, shortValue,
510                     resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.SGET));
511 
512             int intValue = value instanceof Integer ? ((Integer) value).intValue() : -1;
513             setInt(methodHandle, valueHolder, intValue,
514                    resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.IPUT));
515             setInt(methodHandle, intValue,
516                    resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.SPUT));
517             getInt(methodHandle, valueHolder, intValue,
518                    resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.IGET));
519             getInt(methodHandle, intValue,
520                    resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.SGET));
521 
522             long longValue = value instanceof Long ? ((Long) value).longValue() : (long) -1;
523             setLong(methodHandle, valueHolder, longValue,
524                     resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.IPUT));
525             setLong(methodHandle, longValue,
526                     resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.SPUT));
527             getLong(methodHandle, valueHolder, longValue,
528                     resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.IGET));
529             getLong(methodHandle, longValue,
530                     resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.SGET));
531 
532             float floatValue = value instanceof Float ? ((Float) value).floatValue() : -1.0f;
533             setFloat(methodHandle, valueHolder, floatValue,
534                     resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.IPUT));
535             setFloat(methodHandle, floatValue,
536                     resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.SPUT));
537             getFloat(methodHandle, valueHolder, floatValue,
538                     resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.IGET));
539             getFloat(methodHandle, floatValue,
540                      resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.SGET));
541 
542             double doubleValue = value instanceof Double ? ((Double) value).doubleValue() : -1.0;
543             setDouble(methodHandle, valueHolder, doubleValue,
544                       resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.IPUT));
545             setDouble(methodHandle, doubleValue,
546                       resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.SPUT));
547             getDouble(methodHandle, valueHolder, doubleValue,
548                       resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.IGET));
549             getDouble(methodHandle, doubleValue,
550                       resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.SGET));
551 
552             String stringValue = value instanceof String ? ((String) value) : "No Spock, no";
553             setString(methodHandle, valueHolder, stringValue,
554                       resultFor(primitive, PrimitiveType.String, accessor, AccessorType.IPUT));
555             setString(methodHandle, stringValue,
556                       resultFor(primitive, PrimitiveType.String, accessor, AccessorType.SPUT));
557             getString(methodHandle, valueHolder, stringValue,
558                       resultFor(primitive, PrimitiveType.String, accessor, AccessorType.IGET));
559             getString(methodHandle, stringValue,
560                       resultFor(primitive, PrimitiveType.String, accessor, AccessorType.SGET));
561         }
562 
main()563         public static void main() throws Throwable {
564             ValueHolder valueHolder = new ValueHolder();
565             MethodHandles.Lookup lookup = MethodHandles.lookup();
566 
567             boolean [] booleans = { false, true, false };
568             for (boolean b : booleans) {
569                 Boolean boxed = new Boolean(b);
570                 tryAccessor(lookup.findSetter(ValueHolder.class, "m_z", boolean.class),
571                             valueHolder, PrimitiveType.Boolean, boxed, AccessorType.IPUT);
572                 tryAccessor(lookup.findGetter(ValueHolder.class, "m_z", boolean.class),
573                             valueHolder, PrimitiveType.Boolean, boxed, AccessorType.IGET);
574                 assertTrue(valueHolder.m_z == b);
575                 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_z", boolean.class),
576                             valueHolder, PrimitiveType.Boolean, boxed, AccessorType.SPUT);
577                 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_z", boolean.class),
578                             valueHolder, PrimitiveType.Boolean, boxed, AccessorType.SGET);
579                 assertTrue(ValueHolder.s_z == b);
580             }
581 
582             byte [] bytes = { (byte) 0x73, (byte) 0xfe };
583             for (byte b : bytes) {
584                 Byte boxed = new Byte(b);
585                 tryAccessor(lookup.findSetter(ValueHolder.class, "m_b", byte.class),
586                             valueHolder, PrimitiveType.Byte, boxed, AccessorType.IPUT);
587                 tryAccessor(lookup.findGetter(ValueHolder.class, "m_b", byte.class),
588                             valueHolder, PrimitiveType.Byte, boxed, AccessorType.IGET);
589                 assertTrue(valueHolder.m_b == b);
590                 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_b", byte.class),
591                             valueHolder, PrimitiveType.Byte, boxed, AccessorType.SPUT);
592                 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_b", byte.class),
593                             valueHolder, PrimitiveType.Byte, boxed, AccessorType.SGET);
594                 assertTrue(ValueHolder.s_b == b);
595             }
596 
597             char [] chars = { 'a', 'b', 'c' };
598             for (char c : chars) {
599                 Character boxed = new Character(c);
600                 tryAccessor(lookup.findSetter(ValueHolder.class, "m_c", char.class),
601                             valueHolder, PrimitiveType.Char, boxed, AccessorType.IPUT);
602                 tryAccessor(lookup.findGetter(ValueHolder.class, "m_c", char.class),
603                             valueHolder, PrimitiveType.Char, boxed, AccessorType.IGET);
604                 assertTrue(valueHolder.m_c == c);
605                 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_c", char.class),
606                             valueHolder, PrimitiveType.Char, boxed, AccessorType.SPUT);
607                 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_c", char.class),
608                             valueHolder, PrimitiveType.Char, boxed, AccessorType.SGET);
609                 assertTrue(ValueHolder.s_c == c);
610             }
611 
612             short [] shorts = { (short) 0x1234, (short) 0x4321 };
613             for (short s : shorts) {
614                 Short boxed = new Short(s);
615                 tryAccessor(lookup.findSetter(ValueHolder.class, "m_s", short.class),
616                             valueHolder, PrimitiveType.Short, boxed, AccessorType.IPUT);
617                 tryAccessor(lookup.findGetter(ValueHolder.class, "m_s", short.class),
618                             valueHolder, PrimitiveType.Short, boxed, AccessorType.IGET);
619                 assertTrue(valueHolder.m_s == s);
620                 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_s", short.class),
621                             valueHolder, PrimitiveType.Short, boxed, AccessorType.SPUT);
622                 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_s", short.class),
623                             valueHolder, PrimitiveType.Short, boxed, AccessorType.SGET);
624                 assertTrue(ValueHolder.s_s == s);
625             }
626 
627             int [] ints = { -100000000, 10000000 };
628             for (int i : ints) {
629                 Integer boxed = new Integer(i);
630                 tryAccessor(lookup.findSetter(ValueHolder.class, "m_i", int.class),
631                             valueHolder, PrimitiveType.Int, boxed, AccessorType.IPUT);
632                 tryAccessor(lookup.findGetter(ValueHolder.class, "m_i", int.class),
633                             valueHolder, PrimitiveType.Int, boxed, AccessorType.IGET);
634                 assertTrue(valueHolder.m_i == i);
635                 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_i", int.class),
636                             valueHolder, PrimitiveType.Int, boxed, AccessorType.SPUT);
637                 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_i", int.class),
638                             valueHolder, PrimitiveType.Int, boxed, AccessorType.SGET);
639                 assertTrue(ValueHolder.s_i == i);
640             }
641 
642             float [] floats = { 0.99f, -1.23e-17f };
643             for (float f : floats) {
644                 Float boxed = Float.valueOf(f);
645                 tryAccessor(lookup.findSetter(ValueHolder.class, "m_f", float.class),
646                             valueHolder, PrimitiveType.Float, boxed, AccessorType.IPUT);
647                 tryAccessor(lookup.findGetter(ValueHolder.class, "m_f", float.class),
648                             valueHolder, PrimitiveType.Float, boxed, AccessorType.IGET);
649                 assertTrue(valueHolder.m_f == f);
650                 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_f", float.class),
651                             valueHolder, PrimitiveType.Float, boxed, AccessorType.SPUT);
652                 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_f", float.class),
653                             valueHolder, PrimitiveType.Float, boxed, AccessorType.SGET);
654                 assertTrue(ValueHolder.s_f == f);
655             }
656 
657             double [] doubles = { 0.44444444444e37, -0.555555555e-37 };
658             for (double d : doubles) {
659                 Double boxed = Double.valueOf(d);
660                 tryAccessor(lookup.findSetter(ValueHolder.class, "m_d", double.class),
661                             valueHolder, PrimitiveType.Double, boxed, AccessorType.IPUT);
662                 tryAccessor(lookup.findGetter(ValueHolder.class, "m_d", double.class),
663                             valueHolder, PrimitiveType.Double, boxed, AccessorType.IGET);
664                 assertTrue(valueHolder.m_d == d);
665                 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_d", double.class),
666                             valueHolder, PrimitiveType.Double, boxed, AccessorType.SPUT);
667                 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_d", double.class),
668                             valueHolder, PrimitiveType.Double, boxed, AccessorType.SGET);
669                 assertTrue(ValueHolder.s_d == d);
670             }
671 
672             long [] longs = { 0x0123456789abcdefl, 0xfedcba9876543210l };
673             for (long j : longs) {
674                 Long boxed = new Long(j);
675                 tryAccessor(lookup.findSetter(ValueHolder.class, "m_j", long.class),
676                             valueHolder, PrimitiveType.Long, boxed, AccessorType.IPUT);
677                 tryAccessor(lookup.findGetter(ValueHolder.class, "m_j", long.class),
678                             valueHolder, PrimitiveType.Long, boxed, AccessorType.IGET);
679                 assertTrue(valueHolder.m_j == j);
680                 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_j", long.class),
681                             valueHolder, PrimitiveType.Long, boxed, AccessorType.SPUT);
682                 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_j", long.class),
683                             valueHolder, PrimitiveType.Long, boxed, AccessorType.SGET);
684                 assertTrue(ValueHolder.s_j == j);
685             }
686 
687             String [] strings = { "octopus", "crab" };
688             for (String s : strings) {
689                 tryAccessor(lookup.findSetter(ValueHolder.class, "m_l", String.class),
690                             valueHolder, PrimitiveType.String, s, AccessorType.IPUT);
691                 tryAccessor(lookup.findGetter(ValueHolder.class, "m_l", String.class),
692                             valueHolder, PrimitiveType.String, s, AccessorType.IGET);
693                 assertTrue(s.equals(valueHolder.m_l));
694                 tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_l", String.class),
695                             valueHolder, PrimitiveType.String, s, AccessorType.SPUT);
696                 tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_l", String.class),
697                             valueHolder, PrimitiveType.String, s, AccessorType.SGET);
698                 assertTrue(s.equals(ValueHolder.s_l));
699             }
700 
701             System.out.println("Passed MethodHandle.invokeExact() tests for accessors.");
702         }
703     }
704 
705     public static class FindAccessorTester extends Tester {
main()706         public static void main() throws Throwable {
707             // NB having a static field test here is essential for
708             // this test. MethodHandles need to ensure the class
709             // (ValueHolder) is initialized. This happens in the
710             // invoke-polymorphic dispatch.
711             MethodHandles.Lookup lookup = MethodHandles.lookup();
712             {
713                 MethodHandle mh = lookup.findStaticGetter(ValueHolder.class, "s_fi", int.class);
714                 int initialValue = (int) mh.invokeExact();
715                 System.out.println(initialValue);
716             }
717             {
718                 MethodHandle mh = lookup.findStaticSetter(ValueHolder.class, "s_i", int.class);
719                 mh.invokeExact(0);
720             }
721             try {
722                 lookup.findStaticGetter(ValueHolder.class, "s_fi", byte.class);
723                 fail();
724             } catch (NoSuchFieldException expected) {}
725             try {
726                 lookup.findGetter(ValueHolder.class, "s_fi", byte.class);
727                 fail();
728             } catch (NoSuchFieldException eexpected) {}
729             try {
730                 lookup.findStaticSetter(ValueHolder.class, "s_fi", int.class);
731                 fail();
732             } catch (IllegalAccessException expected) {}
733 
734             lookup.findGetter(ValueHolder.class, "m_fi", int.class);
735             try {
736                 lookup.findGetter(ValueHolder.class, "m_fi", byte.class);
737                 fail();
738             } catch (NoSuchFieldException expected) {}
739             try {
740                 lookup.findStaticGetter(ValueHolder.class, "m_fi", byte.class);
741                 fail();
742             } catch (NoSuchFieldException expected) {}
743             try {
744                 lookup.findSetter(ValueHolder.class, "m_fi", int.class);
745                 fail();
746             } catch (IllegalAccessException expected) {}
747 
748             System.out.println("Passed MethodHandles.Lookup tests for accessors.");
749         }
750     }
751 
752     public static class InvokeTester extends Tester {
testStaticGetter()753         private static void testStaticGetter() throws Throwable {
754             MethodHandles.Lookup lookup = MethodHandles.lookup();
755             MethodHandle h0 = lookup.findStaticGetter(ValueHolder.class, "s_fi", int.class);
756             h0.invoke();
757             Number t = (Number) h0.invoke();
758             int u = (int) h0.invoke();
759             Integer v = (Integer) h0.invoke();
760             long w = (long) h0.invoke();
761             try {
762                 byte x = (byte) h0.invoke();
763                 fail();
764             } catch (WrongMethodTypeException expected) {}
765             try {
766                 String y = (String) h0.invoke();
767                 fail();
768             } catch (WrongMethodTypeException expected) {}
769             try {
770                 Long z = (Long) h0.invoke();
771                 fail();
772             } catch (WrongMethodTypeException expected) {}
773         }
774 
testMemberGetter()775         private static void testMemberGetter() throws Throwable {
776             ValueHolder valueHolder = new ValueHolder();
777             MethodHandles.Lookup lookup = MethodHandles.lookup();
778             MethodHandle h0 = lookup.findGetter(ValueHolder.class, "m_fi", int.class);
779             h0.invoke(valueHolder);
780             Number t = (Number) h0.invoke(valueHolder);
781             int u = (int) h0.invoke(valueHolder);
782             Integer v = (Integer) h0.invoke(valueHolder);
783             long w = (long) h0.invoke(valueHolder);
784             try {
785                 byte x = (byte) h0.invoke(valueHolder);
786                 fail();
787             } catch (WrongMethodTypeException expected) {}
788             try {
789                 String y = (String) h0.invoke(valueHolder);
790                 fail();
791             } catch (WrongMethodTypeException expected) {}
792             try {
793                 Long z = (Long) h0.invoke(valueHolder);
794                 fail();
795             } catch (WrongMethodTypeException expected) {}
796         }
797 
getDoubleAsNumber()798         /*package*/ static Number getDoubleAsNumber() {
799             return Double.valueOf(1.4e77);
800         }
getFloatAsNumber()801         /*package*/ static Number getFloatAsNumber() {
802             return Float.valueOf(7.77f);
803         }
getFloatAsObject()804         /*package*/ static Object getFloatAsObject() {
805             return Float.valueOf(-7.77f);
806         }
807 
testMemberSetter()808         private static void testMemberSetter() throws Throwable {
809             ValueHolder valueHolder = new ValueHolder();
810             MethodHandles.Lookup lookup = MethodHandles.lookup();
811             MethodHandle h0 = lookup.findSetter(ValueHolder.class, "m_f", float.class);
812             MethodHandle s0 = lookup.findSetter(ValueHolder.class, "m_s", short.class);
813             h0.invoke(valueHolder, 0.22f);
814             h0.invoke(valueHolder, Float.valueOf(1.11f));
815             Number floatNumber = getFloatAsNumber();
816             h0.invoke(valueHolder, floatNumber);
817             assertTrue(valueHolder.m_f == floatNumber.floatValue());
818             Object objNumber = getFloatAsObject();
819             h0.invoke(valueHolder, objNumber);
820             assertTrue(valueHolder.m_f == ((Float) objNumber).floatValue());
821             try {
822               h0.invoke(valueHolder, (Float) null);
823               fail();
824             } catch (NullPointerException expected) {}
825 
826             // Test that type conversion checks work on small field types.
827             short temp = (short) s0.invoke(valueHolder, new Byte((byte) 45));
828             assertTrue(temp == 0);
829             assertTrue(valueHolder.m_s == 45);
830 
831             h0.invoke(valueHolder, (byte) 1);
832             h0.invoke(valueHolder, (short) 2);
833             h0.invoke(valueHolder, 3);
834             h0.invoke(valueHolder, 4l);
835 
836             assertTrue(null == (Object) h0.invoke(valueHolder, 33));
837             assertTrue(0.0f == (float) h0.invoke(valueHolder, 33));
838             assertTrue(0l == (long) h0.invoke(valueHolder, 33));
839 
840             try {
841                 h0.invoke(valueHolder, 0.33);
842                 fail();
843             } catch (WrongMethodTypeException expected) {}
844             try {
845                 Number doubleNumber = getDoubleAsNumber();
846                 h0.invoke(valueHolder, doubleNumber);
847                 fail();
848             } catch (ClassCastException expected) {}
849             try {
850                 Number doubleNumber = null;
851                 h0.invoke(valueHolder, doubleNumber);
852                 fail();
853             } catch (NullPointerException expected) {}
854             {
855                 // Mismatched return type - float != void
856                 float tmp = (float) h0.invoke(valueHolder, 0.45f);
857                 assertTrue(tmp == 0.0);
858             }
859             try {
860                 h0.invoke(valueHolder, "bam");
861                 fail();
862             } catch (WrongMethodTypeException expected) {}
863             try {
864                 String s = null;
865                 h0.invoke(valueHolder, s);
866                 fail();
867             } catch (WrongMethodTypeException expected) {}
868         }
869 
testStaticSetter()870         private static void testStaticSetter() throws Throwable {
871             MethodHandles.Lookup lookup = MethodHandles.lookup();
872             MethodHandle s0 = lookup.findStaticSetter(ValueHolder.class, "s_s", short.class);
873             MethodHandle h0 = lookup.findStaticSetter(ValueHolder.class, "s_f", float.class);
874             h0.invoke(0.22f);
875             h0.invoke(Float.valueOf(1.11f));
876             Number floatNumber = Float.valueOf(0.88f);
877             h0.invoke(floatNumber);
878             assertTrue(ValueHolder.s_f == floatNumber.floatValue());
879 
880             try {
881               h0.invoke((Float) null);
882               fail();
883             } catch (NullPointerException expected) {}
884 
885             // Test that type conversion checks work on small field types.
886             short temp = (short) s0.invoke(new Byte((byte) 45));
887             assertTrue(temp == 0);
888             assertTrue(ValueHolder.s_s == 45);
889 
890             h0.invoke((byte) 1);
891             h0.invoke((short) 2);
892             h0.invoke(3);
893             h0.invoke(4l);
894 
895             assertTrue(null == (Object) h0.invoke(33));
896             assertTrue(0.0f == (float) h0.invoke(33));
897             assertTrue(0l == (long) h0.invoke(33));
898 
899             try {
900                 h0.invoke(0.33);
901                 fail();
902             } catch (WrongMethodTypeException expected) {}
903             try {
904                 h0.invoke(Double.valueOf(0.33));
905                 fail();
906             } catch (WrongMethodTypeException expected) {}
907             try {
908                 Number doubleNumber = getDoubleAsNumber();
909                 h0.invoke(doubleNumber);
910                 fail();
911             } catch (ClassCastException expected) {}
912             try {
913                 Number doubleNumber = Double.valueOf(1.01);
914                 doubleNumber = (doubleNumber.doubleValue() != 0.1) ? null : doubleNumber;
915                 h0.invoke(doubleNumber);
916                 fail();
917             } catch (NullPointerException expected) {}
918             try {
919                 // Mismatched return type - float != void
920                 float tmp = (float) h0.invoke(0.45f);
921                 assertTrue(tmp == 0.0);
922             } catch (Exception e) { fail(); }
923             try {
924                 h0.invoke("bam");
925                 fail();
926             } catch (WrongMethodTypeException expected) {}
927             try {
928                 String s = null;
929                 h0.invoke(s);
930                 fail();
931             } catch (WrongMethodTypeException expected) {}
932         }
933 
main()934         public static void main() throws Throwable{
935             testStaticGetter();
936             testMemberGetter();
937             testStaticSetter();
938             testMemberSetter();
939             System.out.println("Passed MethodHandle.invoke() tests for accessors.");
940         }
941     }
942 
943     public static class UnreflectTester extends Tester {
main()944         public static void main() throws Throwable {
945             ValueHolder v = new ValueHolder();
946             {
947                 // public field test
948                 Field f = ValueHolder.class.getDeclaredField("m_c");
949                 MethodHandles.lookup().unreflectSetter(f).invokeExact(v, 'z');
950                 assertEquals('z', (char) MethodHandles.lookup().unreflectGetter(f).invokeExact(v));
951                 MethodHandles.lookup().unreflectSetter(f).invokeExact(v, 'A');
952                 assertEquals('A', (char) MethodHandles.lookup().unreflectGetter(f).invokeExact(v));
953             }
954             {
955                 // public static final field test
956                 Field f = ValueHolder.class.getDeclaredField("s_fi");
957                 try {
958                     MethodHandles.lookup().unreflectSetter(f);
959                     fail();
960                 } catch (IllegalAccessException expected) {}
961                 MethodHandles.lookup().unreflectGetter(f);
962                 f.setAccessible(true);
963                 int savedValue = (int) MethodHandles.lookup().unreflectGetter(f).invokeExact();
964                 int newValue = savedValue + 1;
965                 MethodHandles.lookup().unreflectSetter(f).invokeExact(newValue);
966                 assertEquals(newValue, (int) MethodHandles.lookup().unreflectGetter(f).invokeExact()
967                 );
968                 MethodHandles.lookup().unreflectSetter(f).invokeExact(savedValue);
969                 assertEquals(savedValue, (int) MethodHandles.lookup().unreflectGetter(f).invokeExact()
970                 );
971                 f.setAccessible(false);
972                 try {
973                     MethodHandles.lookup().unreflectSetter(f);
974                     fail();
975                 } catch (IllegalAccessException expected) {}
976                 MethodHandles.lookup().unreflectGetter(f);
977             }
978             {
979                 // private field test
980                 Field f = ValueHolder.class.getDeclaredField("m_pz");
981                 try {
982                     MethodHandle mh = MethodHandles.lookup().unreflectSetter(f);
983                     fail();
984                 } catch (IllegalAccessException expected) {}
985                 try {
986                     MethodHandle mh = MethodHandles.lookup().unreflectGetter(f);
987                     fail();
988                 } catch (IllegalAccessException expected) {}
989                 f.setAccessible(true);
990                 MethodHandles.lookup().unreflectSetter(f).invokeExact(v, true);
991                 assertEquals(true, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact(v)
992                 );
993                 MethodHandles.lookup().unreflectSetter(f).invokeExact(v, false);
994                 assertEquals(false, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact(v)
995                 );
996                 f.setAccessible(false);
997                 try {
998                     MethodHandle mh = MethodHandles.lookup().unreflectGetter(f);
999                     fail();
1000                 } catch (IllegalAccessException expected) {}
1001                 try {
1002                     MethodHandle mh = MethodHandles.lookup().unreflectSetter(f);
1003                     fail();
1004                 } catch (IllegalAccessException expected) {}
1005             }
1006             {
1007                 // private static final field test
1008                 Field f = ValueHolder.class.getDeclaredField("s_fz");  // private static final field
1009                 try {
1010                     MethodHandles.lookup().unreflectSetter(f);
1011                     fail();
1012                 } catch (IllegalAccessException expected) {}
1013                 try {
1014                     MethodHandles.lookup().unreflectGetter(f);
1015                     fail();
1016                 } catch (IllegalAccessException expected) {}
1017                 f.setAccessible(true);
1018                 // Setter is okay despite being final because field isAccessible().
1019                 MethodHandles.lookup().unreflectSetter(f).invokeExact(false);
1020                 assertEquals(false, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact()
1021                 );
1022                 MethodHandles.lookup().unreflectSetter(f).invokeExact(true);
1023                 assertEquals(true, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact()
1024                 );
1025                 f.setAccessible(false);
1026                 try {
1027                     MethodHandles.lookup().unreflectSetter(f);
1028                     fail();
1029                 } catch (IllegalAccessException expected) {}
1030                 try {
1031                     MethodHandles.lookup().unreflectGetter(f);
1032                     fail();
1033                 } catch (IllegalAccessException expected) {}
1034             }
1035             System.out.println("Passed MethodHandles.unreflect(Field) tests.");
1036         }
1037     }
1038 
main(String[] args)1039     public static void main(String[] args) throws Throwable {
1040         // FindAccessor test should be the first test class in this
1041         // file to ensure class initialization test is run.
1042         FindAccessorTester.main();
1043         InvokeExactTester.main();
1044         InvokeTester.main();
1045         UnreflectTester.main();
1046     }
1047 }
1048