/*
* 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 {
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) {}
}
/*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) {}
// 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));
}
{
// public static final field test
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) {}
}
{
// private static final field test
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();
}
}