| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| import java.lang.invoke.MethodHandle; |
| import java.lang.invoke.MethodHandles; |
| import java.lang.invoke.WrongMethodTypeException; |
| import java.lang.reflect.Field; |
| |
| public class Main { |
| |
| private static final boolean DALVIK_RUN = "Dalvik".equals(System.getProperty("java.vm.name")); |
| |
| public static class ValueHolder { |
| public boolean m_z = false; |
| public byte m_b = 0; |
| public char m_c = 'a'; |
| public short m_s = 0; |
| public int m_i = 0; |
| public float m_f = 0.0f; |
| public double m_d = 0.0; |
| public long m_j = 0; |
| public String m_l = "a"; |
| |
| public static boolean s_z; |
| public static byte s_b; |
| public static char s_c; |
| public static short s_s; |
| public static int s_i; |
| public static float s_f; |
| public static double s_d; |
| public static long s_j; |
| public static String s_l; |
| |
| public final int m_fi = 0xa5a5a5a5; |
| public static final int s_fi = 0x5a5a5a5a; |
| |
| private boolean m_pz; |
| private static final boolean s_fz = false; |
| } |
| |
| public static class Tester { |
| public static void assertEquals(boolean expected, boolean actual) { |
| if (actual != expected) { |
| throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")"); |
| } |
| } |
| |
| public static void assertEquals(char expected, char actual) { |
| if (actual != expected) { |
| throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")"); |
| } |
| } |
| |
| public static void assertEquals(int expected, int actual) { |
| if (actual != expected) { |
| throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")"); |
| } |
| } |
| |
| public static void assertTrue(boolean value) throws AssertionError { |
| if (!value) { |
| throw new AssertionError("Value is not true"); |
| } |
| } |
| |
| public static void fail() throws Throwable{ |
| throw new Error("fail"); |
| } |
| } |
| |
| public static class InvokeExactTester extends Tester { |
| private enum PrimitiveType { |
| Boolean, |
| Byte, |
| Char, |
| Short, |
| Int, |
| Long, |
| Float, |
| Double, |
| String, |
| } |
| |
| private enum AccessorType { |
| IPUT, |
| SPUT, |
| IGET, |
| SGET, |
| } |
| |
| static void setByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| if (v == null) { |
| m.invokeExact(value); |
| } |
| else { |
| m.invokeExact(v, value); |
| } |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void setByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable { |
| setByte(m, null, value, expectFailure); |
| } |
| |
| static void getByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| final byte got; |
| if (v == null) { |
| got = (byte) m.invokeExact(); |
| } else { |
| got = (byte) m.invokeExact(v); |
| } |
| assertTrue(got == value); |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void getByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable { |
| getByte(m, null, value, expectFailure); |
| } |
| |
| static void setChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| if (v == null) { |
| m.invokeExact(value); |
| } |
| else { |
| m.invokeExact(v, value); |
| } |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void setChar(MethodHandle m, char value, boolean expectFailure) throws Throwable { |
| setChar(m, null, value, expectFailure); |
| } |
| |
| static void getChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| final char got; |
| if (v == null) { |
| got = (char) m.invokeExact(); |
| } else { |
| got = (char) m.invokeExact(v); |
| } |
| assertTrue(got == value); |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void getChar(MethodHandle m, char value, boolean expectFailure) throws Throwable { |
| getChar(m, null, value, expectFailure); |
| } |
| |
| static void setShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| if (v == null) { |
| m.invokeExact(value); |
| } |
| else { |
| m.invokeExact(v, value); |
| } |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void setShort(MethodHandle m, short value, boolean expectFailure) throws Throwable { |
| setShort(m, null, value, expectFailure); |
| } |
| |
| static void getShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| final short got = (v == null) ? (short) m.invokeExact() : (short) m.invokeExact(v); |
| assertTrue(got == value); |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void getShort(MethodHandle m, short value, boolean expectFailure) throws Throwable { |
| getShort(m, null, value, expectFailure); |
| } |
| |
| static void setInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| if (v == null) { |
| m.invokeExact(value); |
| } |
| else { |
| m.invokeExact(v, value); |
| } |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void setInt(MethodHandle m, int value, boolean expectFailure) throws Throwable { |
| setInt(m, null, value, expectFailure); |
| } |
| |
| static void getInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| final int got = (v == null) ? (int) m.invokeExact() : (int) m.invokeExact(v); |
| assertTrue(got == value); |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void getInt(MethodHandle m, int value, boolean expectFailure) throws Throwable { |
| getInt(m, null, value, expectFailure); |
| } |
| |
| static void setLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| if (v == null) { |
| m.invokeExact(value); |
| } |
| else { |
| m.invokeExact(v, value); |
| } |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void setLong(MethodHandle m, long value, boolean expectFailure) throws Throwable { |
| setLong(m, null, value, expectFailure); |
| } |
| |
| static void getLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| final long got = (v == null) ? (long) m.invokeExact() : (long) m.invokeExact(v); |
| assertTrue(got == value); |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void getLong(MethodHandle m, long value, boolean expectFailure) throws Throwable { |
| getLong(m, null, value, expectFailure); |
| } |
| |
| static void setFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| if (v == null) { |
| m.invokeExact(value); |
| } |
| else { |
| m.invokeExact(v, value); |
| } |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void setFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable { |
| setFloat(m, null, value, expectFailure); |
| } |
| |
| static void getFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| final float got = (v == null) ? (float) m.invokeExact() : (float) m.invokeExact(v); |
| assertTrue(got == value); |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void getFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable { |
| getFloat(m, null, value, expectFailure); |
| } |
| |
| static void setDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| if (v == null) { |
| m.invokeExact(value); |
| } |
| else { |
| m.invokeExact(v, value); |
| } |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void setDouble(MethodHandle m, double value, boolean expectFailure) |
| throws Throwable { |
| setDouble(m, null, value, expectFailure); |
| } |
| |
| static void getDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| final double got = (v == null) ? (double) m.invokeExact() : (double) m.invokeExact(v); |
| assertTrue(got == value); |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void getDouble(MethodHandle m, double value, boolean expectFailure) |
| throws Throwable { |
| getDouble(m, null, value, expectFailure); |
| } |
| |
| static void setString(MethodHandle m, ValueHolder v, String value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| if (v == null) { |
| m.invokeExact(value); |
| } |
| else { |
| m.invokeExact(v, value); |
| } |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void setString(MethodHandle m, String value, boolean expectFailure) |
| throws Throwable { |
| setString(m, null, value, expectFailure); |
| } |
| |
| static void getString(MethodHandle m, ValueHolder v, String value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| final String got = (v == null) ? (String) m.invokeExact() : (String) m.invokeExact(v); |
| assertTrue(got.equals(value)); |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void getString(MethodHandle m, String value, boolean expectFailure) |
| throws Throwable { |
| getString(m, null, value, expectFailure); |
| } |
| |
| static void setBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| if (v == null) { |
| m.invokeExact(value); |
| } |
| else { |
| m.invokeExact(v, value); |
| } |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void setBoolean(MethodHandle m, boolean value, boolean expectFailure) |
| throws Throwable { |
| setBoolean(m, null, value, expectFailure); |
| } |
| |
| static void getBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure) |
| throws Throwable { |
| boolean exceptionThrown = false; |
| try { |
| final boolean got = |
| (v == null) ? (boolean) m.invokeExact() : (boolean) m.invokeExact(v); |
| assertTrue(got == value); |
| } |
| catch (WrongMethodTypeException e) { |
| exceptionThrown = true; |
| } |
| assertEquals(expectFailure, exceptionThrown); |
| } |
| |
| static void getBoolean(MethodHandle m, boolean value, boolean expectFailure) |
| throws Throwable { |
| getBoolean(m, null, value, expectFailure); |
| } |
| |
| static boolean resultFor(PrimitiveType actualType, PrimitiveType expectedType, |
| AccessorType actualAccessor, |
| AccessorType expectedAccessor) { |
| return (actualType != expectedType) || (actualAccessor != expectedAccessor); |
| } |
| |
| static void tryAccessor(MethodHandle methodHandle, |
| ValueHolder valueHolder, |
| PrimitiveType primitive, |
| Object value, |
| AccessorType accessor) throws Throwable { |
| boolean booleanValue = |
| value instanceof Boolean ? ((Boolean) value).booleanValue() : false; |
| setBoolean(methodHandle, valueHolder, booleanValue, |
| resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.IPUT)); |
| setBoolean(methodHandle, booleanValue, |
| resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.SPUT)); |
| getBoolean(methodHandle, valueHolder, booleanValue, |
| resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.IGET)); |
| getBoolean(methodHandle, booleanValue, |
| resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.SGET)); |
| |
| byte byteValue = value instanceof Byte ? ((Byte) value).byteValue() : (byte) 0; |
| setByte(methodHandle, valueHolder, byteValue, |
| resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.IPUT)); |
| setByte(methodHandle, byteValue, |
| resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.SPUT)); |
| getByte(methodHandle, valueHolder, byteValue, |
| resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.IGET)); |
| getByte(methodHandle, byteValue, |
| resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.SGET)); |
| |
| char charValue = value instanceof Character ? ((Character) value).charValue() : 'z'; |
| setChar(methodHandle, valueHolder, charValue, |
| resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.IPUT)); |
| setChar(methodHandle, charValue, |
| resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.SPUT)); |
| getChar(methodHandle, valueHolder, charValue, |
| resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.IGET)); |
| getChar(methodHandle, charValue, |
| resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.SGET)); |
| |
| short shortValue = value instanceof Short ? ((Short) value).shortValue() : (short) 0; |
| setShort(methodHandle, valueHolder, shortValue, |
| resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.IPUT)); |
| setShort(methodHandle, shortValue, |
| resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.SPUT)); |
| getShort(methodHandle, valueHolder, shortValue, |
| resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.IGET)); |
| getShort(methodHandle, shortValue, |
| resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.SGET)); |
| |
| int intValue = value instanceof Integer ? ((Integer) value).intValue() : -1; |
| setInt(methodHandle, valueHolder, intValue, |
| resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.IPUT)); |
| setInt(methodHandle, intValue, |
| resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.SPUT)); |
| getInt(methodHandle, valueHolder, intValue, |
| resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.IGET)); |
| getInt(methodHandle, intValue, |
| resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.SGET)); |
| |
| long longValue = value instanceof Long ? ((Long) value).longValue() : (long) -1; |
| setLong(methodHandle, valueHolder, longValue, |
| resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.IPUT)); |
| setLong(methodHandle, longValue, |
| resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.SPUT)); |
| getLong(methodHandle, valueHolder, longValue, |
| resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.IGET)); |
| getLong(methodHandle, longValue, |
| resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.SGET)); |
| |
| float floatValue = value instanceof Float ? ((Float) value).floatValue() : -1.0f; |
| setFloat(methodHandle, valueHolder, floatValue, |
| resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.IPUT)); |
| setFloat(methodHandle, floatValue, |
| resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.SPUT)); |
| getFloat(methodHandle, valueHolder, floatValue, |
| resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.IGET)); |
| getFloat(methodHandle, floatValue, |
| resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.SGET)); |
| |
| double doubleValue = value instanceof Double ? ((Double) value).doubleValue() : -1.0; |
| setDouble(methodHandle, valueHolder, doubleValue, |
| resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.IPUT)); |
| setDouble(methodHandle, doubleValue, |
| resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.SPUT)); |
| getDouble(methodHandle, valueHolder, doubleValue, |
| resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.IGET)); |
| getDouble(methodHandle, doubleValue, |
| resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.SGET)); |
| |
| String stringValue = value instanceof String ? ((String) value) : "No Spock, no"; |
| setString(methodHandle, valueHolder, stringValue, |
| resultFor(primitive, PrimitiveType.String, accessor, AccessorType.IPUT)); |
| setString(methodHandle, stringValue, |
| resultFor(primitive, PrimitiveType.String, accessor, AccessorType.SPUT)); |
| getString(methodHandle, valueHolder, stringValue, |
| resultFor(primitive, PrimitiveType.String, accessor, AccessorType.IGET)); |
| getString(methodHandle, stringValue, |
| resultFor(primitive, PrimitiveType.String, accessor, AccessorType.SGET)); |
| } |
| |
| public static void main() throws Throwable { |
| ValueHolder valueHolder = new ValueHolder(); |
| MethodHandles.Lookup lookup = MethodHandles.lookup(); |
| |
| boolean [] booleans = { false, true, false }; |
| for (boolean b : booleans) { |
| Boolean boxed = new Boolean(b); |
| tryAccessor(lookup.findSetter(ValueHolder.class, "m_z", boolean.class), |
| valueHolder, PrimitiveType.Boolean, boxed, AccessorType.IPUT); |
| tryAccessor(lookup.findGetter(ValueHolder.class, "m_z", boolean.class), |
| valueHolder, PrimitiveType.Boolean, boxed, AccessorType.IGET); |
| assertTrue(valueHolder.m_z == b); |
| tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_z", boolean.class), |
| valueHolder, PrimitiveType.Boolean, boxed, AccessorType.SPUT); |
| tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_z", boolean.class), |
| valueHolder, PrimitiveType.Boolean, boxed, AccessorType.SGET); |
| assertTrue(ValueHolder.s_z == b); |
| } |
| |
| byte [] bytes = { (byte) 0x73, (byte) 0xfe }; |
| for (byte b : bytes) { |
| Byte boxed = new Byte(b); |
| tryAccessor(lookup.findSetter(ValueHolder.class, "m_b", byte.class), |
| valueHolder, PrimitiveType.Byte, boxed, AccessorType.IPUT); |
| tryAccessor(lookup.findGetter(ValueHolder.class, "m_b", byte.class), |
| valueHolder, PrimitiveType.Byte, boxed, AccessorType.IGET); |
| assertTrue(valueHolder.m_b == b); |
| tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_b", byte.class), |
| valueHolder, PrimitiveType.Byte, boxed, AccessorType.SPUT); |
| tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_b", byte.class), |
| valueHolder, PrimitiveType.Byte, boxed, AccessorType.SGET); |
| assertTrue(ValueHolder.s_b == b); |
| } |
| |
| char [] chars = { 'a', 'b', 'c' }; |
| for (char c : chars) { |
| Character boxed = new Character(c); |
| tryAccessor(lookup.findSetter(ValueHolder.class, "m_c", char.class), |
| valueHolder, PrimitiveType.Char, boxed, AccessorType.IPUT); |
| tryAccessor(lookup.findGetter(ValueHolder.class, "m_c", char.class), |
| valueHolder, PrimitiveType.Char, boxed, AccessorType.IGET); |
| assertTrue(valueHolder.m_c == c); |
| tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_c", char.class), |
| valueHolder, PrimitiveType.Char, boxed, AccessorType.SPUT); |
| tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_c", char.class), |
| valueHolder, PrimitiveType.Char, boxed, AccessorType.SGET); |
| assertTrue(ValueHolder.s_c == c); |
| } |
| |
| short [] shorts = { (short) 0x1234, (short) 0x4321 }; |
| for (short s : shorts) { |
| Short boxed = new Short(s); |
| tryAccessor(lookup.findSetter(ValueHolder.class, "m_s", short.class), |
| valueHolder, PrimitiveType.Short, boxed, AccessorType.IPUT); |
| tryAccessor(lookup.findGetter(ValueHolder.class, "m_s", short.class), |
| valueHolder, PrimitiveType.Short, boxed, AccessorType.IGET); |
| assertTrue(valueHolder.m_s == s); |
| tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_s", short.class), |
| valueHolder, PrimitiveType.Short, boxed, AccessorType.SPUT); |
| tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_s", short.class), |
| valueHolder, PrimitiveType.Short, boxed, AccessorType.SGET); |
| assertTrue(ValueHolder.s_s == s); |
| } |
| |
| int [] ints = { -100000000, 10000000 }; |
| for (int i : ints) { |
| Integer boxed = new Integer(i); |
| tryAccessor(lookup.findSetter(ValueHolder.class, "m_i", int.class), |
| valueHolder, PrimitiveType.Int, boxed, AccessorType.IPUT); |
| tryAccessor(lookup.findGetter(ValueHolder.class, "m_i", int.class), |
| valueHolder, PrimitiveType.Int, boxed, AccessorType.IGET); |
| assertTrue(valueHolder.m_i == i); |
| tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_i", int.class), |
| valueHolder, PrimitiveType.Int, boxed, AccessorType.SPUT); |
| tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_i", int.class), |
| valueHolder, PrimitiveType.Int, boxed, AccessorType.SGET); |
| assertTrue(ValueHolder.s_i == i); |
| } |
| |
| float [] floats = { 0.99f, -1.23e-17f }; |
| for (float f : floats) { |
| Float boxed = Float.valueOf(f); |
| tryAccessor(lookup.findSetter(ValueHolder.class, "m_f", float.class), |
| valueHolder, PrimitiveType.Float, boxed, AccessorType.IPUT); |
| tryAccessor(lookup.findGetter(ValueHolder.class, "m_f", float.class), |
| valueHolder, PrimitiveType.Float, boxed, AccessorType.IGET); |
| assertTrue(valueHolder.m_f == f); |
| tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_f", float.class), |
| valueHolder, PrimitiveType.Float, boxed, AccessorType.SPUT); |
| tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_f", float.class), |
| valueHolder, PrimitiveType.Float, boxed, AccessorType.SGET); |
| assertTrue(ValueHolder.s_f == f); |
| } |
| |
| double [] doubles = { 0.44444444444e37, -0.555555555e-37 }; |
| for (double d : doubles) { |
| Double boxed = Double.valueOf(d); |
| tryAccessor(lookup.findSetter(ValueHolder.class, "m_d", double.class), |
| valueHolder, PrimitiveType.Double, boxed, AccessorType.IPUT); |
| tryAccessor(lookup.findGetter(ValueHolder.class, "m_d", double.class), |
| valueHolder, PrimitiveType.Double, boxed, AccessorType.IGET); |
| assertTrue(valueHolder.m_d == d); |
| tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_d", double.class), |
| valueHolder, PrimitiveType.Double, boxed, AccessorType.SPUT); |
| tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_d", double.class), |
| valueHolder, PrimitiveType.Double, boxed, AccessorType.SGET); |
| assertTrue(ValueHolder.s_d == d); |
| } |
| |
| long [] longs = { 0x0123456789abcdefl, 0xfedcba9876543210l }; |
| for (long j : longs) { |
| Long boxed = new Long(j); |
| tryAccessor(lookup.findSetter(ValueHolder.class, "m_j", long.class), |
| valueHolder, PrimitiveType.Long, boxed, AccessorType.IPUT); |
| tryAccessor(lookup.findGetter(ValueHolder.class, "m_j", long.class), |
| valueHolder, PrimitiveType.Long, boxed, AccessorType.IGET); |
| assertTrue(valueHolder.m_j == j); |
| tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_j", long.class), |
| valueHolder, PrimitiveType.Long, boxed, AccessorType.SPUT); |
| tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_j", long.class), |
| valueHolder, PrimitiveType.Long, boxed, AccessorType.SGET); |
| assertTrue(ValueHolder.s_j == j); |
| } |
| |
| String [] strings = { "octopus", "crab" }; |
| for (String s : strings) { |
| tryAccessor(lookup.findSetter(ValueHolder.class, "m_l", String.class), |
| valueHolder, PrimitiveType.String, s, AccessorType.IPUT); |
| tryAccessor(lookup.findGetter(ValueHolder.class, "m_l", String.class), |
| valueHolder, PrimitiveType.String, s, AccessorType.IGET); |
| assertTrue(s.equals(valueHolder.m_l)); |
| tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_l", String.class), |
| valueHolder, PrimitiveType.String, s, AccessorType.SPUT); |
| tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_l", String.class), |
| valueHolder, PrimitiveType.String, s, AccessorType.SGET); |
| assertTrue(s.equals(ValueHolder.s_l)); |
| } |
| |
| System.out.println("Passed MethodHandle.invokeExact() tests for accessors."); |
| } |
| } |
| |
| public static class FindAccessorTester extends Tester { |
| public static void main() throws Throwable { |
| // NB having a static field test here is essential for |
| // this test. MethodHandles need to ensure the class |
| // (ValueHolder) is initialized. This happens in the |
| // invoke-polymorphic dispatch. |
| MethodHandles.Lookup lookup = MethodHandles.lookup(); |
| { |
| MethodHandle mh = lookup.findStaticGetter(ValueHolder.class, "s_fi", int.class); |
| int initialValue = (int) mh.invokeExact(); |
| System.out.println(initialValue); |
| } |
| { |
| MethodHandle mh = lookup.findStaticSetter(ValueHolder.class, "s_i", int.class); |
| mh.invokeExact(0); |
| } |
| try { |
| lookup.findStaticGetter(ValueHolder.class, "s_fi", byte.class); |
| fail(); |
| } catch (NoSuchFieldException expected) {} |
| try { |
| lookup.findGetter(ValueHolder.class, "s_fi", byte.class); |
| fail(); |
| } catch (NoSuchFieldException eexpected) {} |
| try { |
| lookup.findStaticSetter(ValueHolder.class, "s_fi", int.class); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| |
| lookup.findGetter(ValueHolder.class, "m_fi", int.class); |
| try { |
| lookup.findGetter(ValueHolder.class, "m_fi", byte.class); |
| fail(); |
| } catch (NoSuchFieldException expected) {} |
| try { |
| lookup.findStaticGetter(ValueHolder.class, "m_fi", byte.class); |
| fail(); |
| } catch (NoSuchFieldException expected) {} |
| try { |
| lookup.findSetter(ValueHolder.class, "m_fi", int.class); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| |
| System.out.println("Passed MethodHandles.Lookup tests for accessors."); |
| } |
| } |
| |
| public static class InvokeTester extends Tester { |
| private static void testStaticGetter() throws Throwable { |
| MethodHandles.Lookup lookup = MethodHandles.lookup(); |
| MethodHandle h0 = lookup.findStaticGetter(ValueHolder.class, "s_fi", int.class); |
| h0.invoke(); |
| Number t = (Number) h0.invoke(); |
| int u = (int) h0.invoke(); |
| Integer v = (Integer) h0.invoke(); |
| long w = (long) h0.invoke(); |
| try { |
| byte x = (byte) h0.invoke(); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| try { |
| String y = (String) h0.invoke(); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| try { |
| Long z = (Long) h0.invoke(); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| } |
| |
| private static void testMemberGetter() throws Throwable { |
| ValueHolder valueHolder = new ValueHolder(); |
| MethodHandles.Lookup lookup = MethodHandles.lookup(); |
| MethodHandle h0 = lookup.findGetter(ValueHolder.class, "m_fi", int.class); |
| h0.invoke(valueHolder); |
| Number t = (Number) h0.invoke(valueHolder); |
| int u = (int) h0.invoke(valueHolder); |
| Integer v = (Integer) h0.invoke(valueHolder); |
| long w = (long) h0.invoke(valueHolder); |
| try { |
| byte x = (byte) h0.invoke(valueHolder); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| try { |
| String y = (String) h0.invoke(valueHolder); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| try { |
| Long z = (Long) h0.invoke(valueHolder); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| try { |
| int x = (int) h0.invokeExact((ValueHolder) null); |
| fail(); |
| } catch (NullPointerException expected) {} |
| } |
| |
| /*package*/ static Number getDoubleAsNumber() { |
| return Double.valueOf(1.4e77); |
| } |
| /*package*/ static Number getFloatAsNumber() { |
| return Float.valueOf(7.77f); |
| } |
| /*package*/ static Object getFloatAsObject() { |
| return Float.valueOf(-7.77f); |
| } |
| |
| private static void testMemberSetter() throws Throwable { |
| ValueHolder valueHolder = new ValueHolder(); |
| MethodHandles.Lookup lookup = MethodHandles.lookup(); |
| MethodHandle h0 = lookup.findSetter(ValueHolder.class, "m_f", float.class); |
| MethodHandle s0 = lookup.findSetter(ValueHolder.class, "m_s", short.class); |
| h0.invoke(valueHolder, 0.22f); |
| h0.invoke(valueHolder, Float.valueOf(1.11f)); |
| Number floatNumber = getFloatAsNumber(); |
| h0.invoke(valueHolder, floatNumber); |
| assertTrue(valueHolder.m_f == floatNumber.floatValue()); |
| Object objNumber = getFloatAsObject(); |
| h0.invoke(valueHolder, objNumber); |
| assertTrue(valueHolder.m_f == ((Float) objNumber).floatValue()); |
| try { |
| h0.invoke(valueHolder, (Float) null); |
| fail(); |
| } catch (NullPointerException expected) {} |
| try { |
| h0.invoke((ValueHolder) null, Float.valueOf(1.0f)); |
| fail(); |
| } catch (NullPointerException expected) {} |
| |
| // Test that type conversion checks work on small field types. |
| short temp = (short) s0.invoke(valueHolder, new Byte((byte) 45)); |
| assertTrue(temp == 0); |
| assertTrue(valueHolder.m_s == 45); |
| |
| h0.invoke(valueHolder, (byte) 1); |
| h0.invoke(valueHolder, (short) 2); |
| h0.invoke(valueHolder, 3); |
| h0.invoke(valueHolder, 4l); |
| |
| assertTrue(null == (Object) h0.invoke(valueHolder, 33)); |
| assertTrue(0.0f == (float) h0.invoke(valueHolder, 33)); |
| assertTrue(0l == (long) h0.invoke(valueHolder, 33)); |
| |
| try { |
| h0.invoke(valueHolder, 0.33); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| try { |
| Number doubleNumber = getDoubleAsNumber(); |
| h0.invoke(valueHolder, doubleNumber); |
| fail(); |
| } catch (ClassCastException expected) {} |
| try { |
| Number doubleNumber = null; |
| h0.invoke(valueHolder, doubleNumber); |
| fail(); |
| } catch (NullPointerException expected) {} |
| { |
| // Mismatched return type - float != void |
| float tmp = (float) h0.invoke(valueHolder, 0.45f); |
| assertTrue(tmp == 0.0); |
| } |
| try { |
| h0.invoke(valueHolder, "bam"); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| try { |
| String s = null; |
| h0.invoke(valueHolder, s); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| } |
| |
| private static void testStaticSetter() throws Throwable { |
| MethodHandles.Lookup lookup = MethodHandles.lookup(); |
| MethodHandle s0 = lookup.findStaticSetter(ValueHolder.class, "s_s", short.class); |
| MethodHandle h0 = lookup.findStaticSetter(ValueHolder.class, "s_f", float.class); |
| h0.invoke(0.22f); |
| h0.invoke(Float.valueOf(1.11f)); |
| Number floatNumber = Float.valueOf(0.88f); |
| h0.invoke(floatNumber); |
| assertTrue(ValueHolder.s_f == floatNumber.floatValue()); |
| |
| try { |
| h0.invoke((Float) null); |
| fail(); |
| } catch (NullPointerException expected) {} |
| |
| // Test that type conversion checks work on small field types. |
| short temp = (short) s0.invoke(new Byte((byte) 45)); |
| assertTrue(temp == 0); |
| assertTrue(ValueHolder.s_s == 45); |
| |
| h0.invoke((byte) 1); |
| h0.invoke((short) 2); |
| h0.invoke(3); |
| h0.invoke(4l); |
| |
| assertTrue(null == (Object) h0.invoke(33)); |
| assertTrue(0.0f == (float) h0.invoke(33)); |
| assertTrue(0l == (long) h0.invoke(33)); |
| |
| try { |
| h0.invoke(0.33); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| try { |
| h0.invoke(Double.valueOf(0.33)); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| try { |
| Number doubleNumber = getDoubleAsNumber(); |
| h0.invoke(doubleNumber); |
| fail(); |
| } catch (ClassCastException expected) {} |
| try { |
| Number doubleNumber = Double.valueOf(1.01); |
| doubleNumber = (doubleNumber.doubleValue() != 0.1) ? null : doubleNumber; |
| h0.invoke(doubleNumber); |
| fail(); |
| } catch (NullPointerException expected) {} |
| try { |
| // Mismatched return type - float != void |
| float tmp = (float) h0.invoke(0.45f); |
| assertTrue(tmp == 0.0); |
| } catch (Exception e) { fail(); } |
| try { |
| h0.invoke("bam"); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| try { |
| String s = null; |
| h0.invoke(s); |
| fail(); |
| } catch (WrongMethodTypeException expected) {} |
| } |
| |
| public static void main() throws Throwable{ |
| testStaticGetter(); |
| testMemberGetter(); |
| testStaticSetter(); |
| testMemberSetter(); |
| System.out.println("Passed MethodHandle.invoke() tests for accessors."); |
| } |
| } |
| |
| public static class UnreflectTester extends Tester { |
| public static void main() throws Throwable { |
| ValueHolder v = new ValueHolder(); |
| { |
| // public field test |
| Field f = ValueHolder.class.getDeclaredField("m_c"); |
| MethodHandles.lookup().unreflectSetter(f).invokeExact(v, 'z'); |
| assertEquals('z', (char) MethodHandles.lookup().unreflectGetter(f).invokeExact(v)); |
| MethodHandles.lookup().unreflectSetter(f).invokeExact(v, 'A'); |
| assertEquals('A', (char) MethodHandles.lookup().unreflectGetter(f).invokeExact(v)); |
| } |
| if (DALVIK_RUN) { |
| // public static final field test |
| // for JVM it is not possible to get the unreflected setter for a static final |
| // field, see b/242985782 |
| Field f = ValueHolder.class.getDeclaredField("s_fi"); |
| try { |
| MethodHandles.lookup().unreflectSetter(f); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| MethodHandles.lookup().unreflectGetter(f); |
| f.setAccessible(true); |
| int savedValue = (int) MethodHandles.lookup().unreflectGetter(f).invokeExact(); |
| int newValue = savedValue + 1; |
| MethodHandles.lookup().unreflectSetter(f).invokeExact(newValue); |
| assertEquals(newValue, (int) MethodHandles.lookup().unreflectGetter(f).invokeExact() |
| ); |
| MethodHandles.lookup().unreflectSetter(f).invokeExact(savedValue); |
| assertEquals(savedValue, (int) MethodHandles.lookup().unreflectGetter(f).invokeExact() |
| ); |
| f.setAccessible(false); |
| try { |
| MethodHandles.lookup().unreflectSetter(f); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| MethodHandles.lookup().unreflectGetter(f); |
| } |
| { |
| // private field test |
| Field f = ValueHolder.class.getDeclaredField("m_pz"); |
| try { |
| MethodHandle mh = MethodHandles.lookup().unreflectSetter(f); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| try { |
| MethodHandle mh = MethodHandles.lookup().unreflectGetter(f); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| f.setAccessible(true); |
| MethodHandles.lookup().unreflectSetter(f).invokeExact(v, true); |
| assertEquals(true, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact(v) |
| ); |
| MethodHandles.lookup().unreflectSetter(f).invokeExact(v, false); |
| assertEquals(false, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact(v) |
| ); |
| f.setAccessible(false); |
| try { |
| MethodHandle mh = MethodHandles.lookup().unreflectGetter(f); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| try { |
| MethodHandle mh = MethodHandles.lookup().unreflectSetter(f); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| } |
| if (DALVIK_RUN) { |
| // private static final field test |
| // for JVM it is not possible to get the unreflected setter for a static final |
| // field, see b/242985782 |
| Field f = ValueHolder.class.getDeclaredField("s_fz"); // private static final field |
| try { |
| MethodHandles.lookup().unreflectSetter(f); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| try { |
| MethodHandles.lookup().unreflectGetter(f); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| f.setAccessible(true); |
| // Setter is okay despite being final because field isAccessible(). |
| MethodHandles.lookup().unreflectSetter(f).invokeExact(false); |
| assertEquals(false, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact() |
| ); |
| MethodHandles.lookup().unreflectSetter(f).invokeExact(true); |
| assertEquals(true, (boolean) MethodHandles.lookup().unreflectGetter(f).invokeExact() |
| ); |
| f.setAccessible(false); |
| try { |
| MethodHandles.lookup().unreflectSetter(f); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| try { |
| MethodHandles.lookup().unreflectGetter(f); |
| fail(); |
| } catch (IllegalAccessException expected) {} |
| } |
| System.out.println("Passed MethodHandles.unreflect(Field) tests."); |
| } |
| } |
| |
| public static void main(String[] args) throws Throwable { |
| // FindAccessor test should be the first test class in this |
| // file to ensure class initialization test is run. |
| FindAccessorTester.main(); |
| InvokeExactTester.main(); |
| InvokeTester.main(); |
| UnreflectTester.main(); |
| } |
| } |