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