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 */
16import java.lang.invoke.MethodHandle;
17import java.lang.invoke.MethodHandles;
18import java.lang.invoke.WrongMethodTypeException;
19import java.lang.reflect.Field;
20
21public 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 {
52        public static void assertEquals(boolean expected, boolean actual) {
53            if (actual != expected) {
54                throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")");
55            }
56        }
57
58        public static void assertEquals(char expected, char actual) {
59            if (actual != expected) {
60                throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")");
61            }
62        }
63
64        public static void assertEquals(int expected, int actual) {
65            if (actual != expected) {
66                throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")");
67            }
68        }
69
70        public static void assertTrue(boolean value) throws AssertionError {
71            if (!value) {
72                throw new AssertionError("Value is not true");
73            }
74        }
75
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
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
118        static void setByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable {
119            setByte(m, null, value, expectFailure);
120        }
121
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
140        static void getByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable {
141            getByte(m, null, value, expectFailure);
142        }
143
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
161        static void setChar(MethodHandle m, char value, boolean expectFailure) throws Throwable {
162            setChar(m, null, value, expectFailure);
163        }
164
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
183        static void getChar(MethodHandle m, char value, boolean expectFailure) throws Throwable {
184            getChar(m, null, value, expectFailure);
185        }
186
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
204        static void setShort(MethodHandle m, short value, boolean expectFailure) throws Throwable {
205            setShort(m, null, value, expectFailure);
206        }
207
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
221        static void getShort(MethodHandle m, short value, boolean expectFailure) throws Throwable {
222            getShort(m, null, value, expectFailure);
223        }
224
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
242        static void setInt(MethodHandle m, int value, boolean expectFailure) throws Throwable {
243            setInt(m, null, value, expectFailure);
244        }
245
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
259        static void getInt(MethodHandle m, int value, boolean expectFailure) throws Throwable {
260            getInt(m, null, value, expectFailure);
261        }
262
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
280        static void setLong(MethodHandle m, long value, boolean expectFailure) throws Throwable {
281            setLong(m, null, value, expectFailure);
282        }
283
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
297        static void getLong(MethodHandle m, long value, boolean expectFailure) throws Throwable {
298            getLong(m, null, value, expectFailure);
299        }
300
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
318        static void setFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable {
319            setFloat(m, null, value, expectFailure);
320        }
321
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
335        static void getFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable {
336            getFloat(m, null, value, expectFailure);
337        }
338
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
356        static void setDouble(MethodHandle m, double value, boolean expectFailure)
357                throws Throwable {
358            setDouble(m, null, value, expectFailure);
359        }
360
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
374        static void getDouble(MethodHandle m, double value, boolean expectFailure)
375                throws Throwable {
376            getDouble(m, null, value, expectFailure);
377        }
378
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
396        static void setString(MethodHandle m, String value, boolean expectFailure)
397                throws Throwable {
398            setString(m, null, value, expectFailure);
399        }
400
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
414        static void getString(MethodHandle m, String value, boolean expectFailure)
415                throws Throwable {
416            getString(m, null, value, expectFailure);
417        }
418
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
436        static void setBoolean(MethodHandle m, boolean value, boolean expectFailure)
437                throws Throwable {
438            setBoolean(m, null, value, expectFailure);
439        }
440
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
455        static void getBoolean(MethodHandle m, boolean value, boolean expectFailure)
456                throws Throwable {
457            getBoolean(m, null, value, expectFailure);
458        }
459
460        static boolean resultFor(PrimitiveType actualType, PrimitiveType expectedType,
461                                 AccessorType actualAccessor,
462                                 AccessorType expectedAccessor) {
463            return (actualType != expectedType) || (actualAccessor != expectedAccessor);
464        }
465
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
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 {
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 {
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
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
798        /*package*/ static Number getDoubleAsNumber() {
799            return Double.valueOf(1.4e77);
800        }
801        /*package*/ static Number getFloatAsNumber() {
802            return Float.valueOf(7.77f);
803        }
804        /*package*/ static Object getFloatAsObject() {
805            return Float.valueOf(-7.77f);
806        }
807
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
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
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 {
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
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