ART: Tests for MethodHandle.Lookup#unreflect{G,S}etter
Bug: 30550796
Bug: 67730310
Test: art/test.py --host -t 959
Change-Id: I74cc0c41d50650f5efe6727f2a97a743e41ed8ff
diff --git a/test/959-invoke-polymorphic-accessors/expected.txt b/test/959-invoke-polymorphic-accessors/expected.txt
index de2916b..9df450b 100644
--- a/test/959-invoke-polymorphic-accessors/expected.txt
+++ b/test/959-invoke-polymorphic-accessors/expected.txt
@@ -2,3 +2,4 @@
Passed MethodHandles.Lookup tests for accessors.
Passed MethodHandle.invokeExact() tests for accessors.
Passed MethodHandle.invoke() tests for accessors.
+Passed MethodHandles.unreflect(Field) tests.
diff --git a/test/959-invoke-polymorphic-accessors/src/Main.java b/test/959-invoke-polymorphic-accessors/src/Main.java
index 59db807..7939a1b 100644
--- a/test/959-invoke-polymorphic-accessors/src/Main.java
+++ b/test/959-invoke-polymorphic-accessors/src/Main.java
@@ -16,6 +16,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.WrongMethodTypeException;
+import java.lang.reflect.Field;
public class Main {
@@ -42,16 +43,31 @@
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 assertActualAndExpectedMatch(boolean actual, boolean expected)
+ public static void assertEquals(boolean actual, boolean expected)
throws AssertionError {
if (actual != expected) {
throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")");
}
}
+ public static void assertEquals(char actual, char expected) {
+ if (actual != expected) {
+ throw new AssertionError("Actual != Expected (" + actual + " != " + expected + ")");
+ }
+ }
+
+ public static void assertEquals(int actual, int expected) {
+ 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");
@@ -97,7 +113,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void setByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable {
@@ -119,7 +135,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void getByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable {
@@ -140,7 +156,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void setChar(MethodHandle m, char value, boolean expectFailure) throws Throwable {
@@ -162,7 +178,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void getChar(MethodHandle m, char value, boolean expectFailure) throws Throwable {
@@ -183,7 +199,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void setShort(MethodHandle m, short value, boolean expectFailure) throws Throwable {
@@ -200,7 +216,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void getShort(MethodHandle m, short value, boolean expectFailure) throws Throwable {
@@ -221,7 +237,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void setInt(MethodHandle m, int value, boolean expectFailure) throws Throwable {
@@ -238,7 +254,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void getInt(MethodHandle m, int value, boolean expectFailure) throws Throwable {
@@ -259,7 +275,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void setLong(MethodHandle m, long value, boolean expectFailure) throws Throwable {
@@ -276,7 +292,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void getLong(MethodHandle m, long value, boolean expectFailure) throws Throwable {
@@ -297,7 +313,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void setFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable {
@@ -314,7 +330,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void getFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable {
@@ -335,7 +351,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void setDouble(MethodHandle m, double value, boolean expectFailure)
@@ -353,7 +369,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void getDouble(MethodHandle m, double value, boolean expectFailure)
@@ -375,7 +391,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void setString(MethodHandle m, String value, boolean expectFailure)
@@ -393,7 +409,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void getString(MethodHandle m, String value, boolean expectFailure)
@@ -415,7 +431,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void setBoolean(MethodHandle m, boolean value, boolean expectFailure)
@@ -434,7 +450,7 @@
catch (WrongMethodTypeException e) {
exceptionThrown = true;
}
- assertActualAndExpectedMatch(exceptionThrown, expectFailure);
+ assertEquals(exceptionThrown, expectFailure);
}
static void getBoolean(MethodHandle m, boolean value, boolean expectFailure)
@@ -694,15 +710,15 @@
// (ValueHolder) is initialized. This happens in the
// invoke-polymorphic dispatch.
MethodHandles.Lookup lookup = MethodHandles.lookup();
- try {
+ {
MethodHandle mh = lookup.findStaticGetter(ValueHolder.class, "s_fi", int.class);
int initialValue = (int)mh.invokeExact();
System.out.println(initialValue);
- } catch (NoSuchFieldException e) { unreachable(); }
- try {
+ }
+ {
MethodHandle mh = lookup.findStaticSetter(ValueHolder.class, "s_i", int.class);
mh.invokeExact(0);
- } catch (NoSuchFieldException e) { unreachable(); }
+ }
try {
lookup.findStaticGetter(ValueHolder.class, "s_fi", byte.class);
unreachable();
@@ -836,11 +852,11 @@
h0.invoke(valueHolder, doubleNumber);
unreachable();
} catch (NullPointerException e) {}
- try {
+ {
// Mismatched return type - float != void
float tmp = (float)h0.invoke(valueHolder, 0.45f);
assertTrue(tmp == 0.0);
- } catch (Exception e) { unreachable(); }
+ }
try {
h0.invoke(valueHolder, "bam");
unreachable();
@@ -921,11 +937,108 @@
}
}
+ 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((char)MethodHandles.lookup().unreflectGetter(f).invokeExact(v), 'z');
+ MethodHandles.lookup().unreflectSetter(f).invokeExact(v, 'A');
+ assertEquals((char)MethodHandles.lookup().unreflectGetter(f).invokeExact(v), 'A');
+ }
+ {
+ // public static final field test
+ Field f = ValueHolder.class.getDeclaredField("s_fi");
+ try {
+ MethodHandles.lookup().unreflectSetter(f);
+ unreachable();
+ } catch (IllegalAccessException e) {}
+ 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((int)MethodHandles.lookup().unreflectGetter(f).invokeExact(),
+ newValue);
+ MethodHandles.lookup().unreflectSetter(f).invokeExact(savedValue);
+ assertEquals((int)MethodHandles.lookup().unreflectGetter(f).invokeExact(),
+ savedValue);
+ f.setAccessible(false);
+ try {
+ MethodHandles.lookup().unreflectSetter(f);
+ unreachable();
+ } catch (IllegalAccessException e) {}
+ MethodHandles.lookup().unreflectGetter(f);
+ }
+ {
+ // private field test
+ Field f = ValueHolder.class.getDeclaredField("m_pz");
+ try {
+ MethodHandle mh = MethodHandles.lookup().unreflectSetter(f);
+ unreachable();
+ } catch (IllegalAccessException e) {}
+ try {
+ MethodHandle mh = MethodHandles.lookup().unreflectGetter(f);
+ unreachable();
+ } catch (IllegalAccessException e) {}
+ f.setAccessible(true);
+ MethodHandles.lookup().unreflectSetter(f).invokeExact(v, true);
+ assertEquals((boolean)MethodHandles.lookup().unreflectGetter(f).invokeExact(v),
+ true);
+ MethodHandles.lookup().unreflectSetter(f).invokeExact(v, false);
+ assertEquals((boolean)MethodHandles.lookup().unreflectGetter(f).invokeExact(v),
+ false);
+ f.setAccessible(false);
+ try {
+ MethodHandle mh = MethodHandles.lookup().unreflectGetter(f);
+ unreachable();
+ } catch (IllegalAccessException e) {}
+ try {
+ MethodHandle mh = MethodHandles.lookup().unreflectSetter(f);
+ unreachable();
+ } catch (IllegalAccessException e) {}
+ }
+ {
+ // private static final field test
+ Field f = ValueHolder.class.getDeclaredField("s_fz"); // private static final field
+ try {
+ MethodHandles.lookup().unreflectSetter(f);
+ unreachable();
+ } catch (IllegalAccessException e) {}
+ try {
+ MethodHandles.lookup().unreflectGetter(f);
+ unreachable();
+ } catch (IllegalAccessException e) {}
+ f.setAccessible(true);
+ // Setter is okay despite being final because field isAccessible().
+ MethodHandles.lookup().unreflectSetter(f).invokeExact(false);
+ assertEquals((boolean)MethodHandles.lookup().unreflectGetter(f).invokeExact(),
+ false);
+ MethodHandles.lookup().unreflectSetter(f).invokeExact(true);
+ assertEquals((boolean)MethodHandles.lookup().unreflectGetter(f).invokeExact(),
+ true);
+ f.setAccessible(false);
+ try {
+ MethodHandles.lookup().unreflectSetter(f);
+ unreachable();
+ } catch (IllegalAccessException e) {}
+ try {
+ MethodHandles.lookup().unreflectGetter(f);
+ unreachable();
+ } catch (IllegalAccessException e) {}
+ }
+ 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();
}
}