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