MethodHandlesTest.java revision 5455
0N/A * @compile -source 7 -target 7 MethodHandlesTest.java
0N/Apublic class MethodHandlesTest {
0N/A static boolean CAN_SKIP_WORKING = false;
0N/A static boolean CAN_TEST_LIGHTLY = Boolean.getBoolean(THIS_CLASS.getName()+".CAN_TEST_LIGHTLY");
0N/A // AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters
0N/A @Test //@Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args")
0N/A // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
0N/A // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
0N/A // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
0N/A // ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13
0N/A public MethodHandlesTest() {
0N/A public void printCounts() {
0N/A if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run");
0N/A if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run");
return entry;
return (int)(value);
return (long)(value);
return (char)(value);
return (short)(value);
return (float)(value);
return (double)(value);
return (byte)(value);
return null;
static long nextArgVal;
if (moreBits)
static int nextArg() {
return (int) nextArg(false);
return nextArg(true);
return (long) nextArg();
return wrap;
{ param = c; break; }
return args;
return args;
static <T> T[] cat(T[] a, T... b) {
return res;
if (x == null) return x;
if (x instanceof List) {
public static interface IntExample {
public void v0();
{ { false, PUBLIC }, { false, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[1]: only PRIVATE
if (pubc)
return cases;
@Test
if (CAN_SKIP_WORKING) return;
void testFindStatic(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
void testFindStatic(Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
void testFindStatic(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
static final boolean DEBUG_METHOD_HANDLE_NAMES = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
if (!DEBUG_METHOD_HANDLE_NAMES) {
assertEquals(s, x);
@Test
if (CAN_SKIP_WORKING) return;
void testFindVirtual(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
void testFindVirtual(Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
void testFindVirtual(Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
@Test
if (CAN_SKIP_WORKING) return;
System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
@Test
if (CAN_SKIP_WORKING) return;
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
@Test
if (CAN_SKIP_WORKING) return;
void testBind(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
@Test
if (CAN_SKIP_WORKING) return;
void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable {
testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params);
void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
if (isSpecial)
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
if (!isStatic) {
if (isStatic) {
if (isSpecial)
void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
@Test
if (CAN_SKIP_WORKING) return;
testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0");
public static class HasFields {
boolean fZ = false;
static boolean sZ = true;
if (type == float.class) {
if (isStatic) v++;
cases.add(new Object[]{ new Object[]{ false, HasFields.class, "bogus_fD", double.class }, Error.class });
cases.add(new Object[]{ new Object[]{ true, HasFields.class, "bogus_sL", Object.class }, Error.class });
switch (testMode) {
@Test
@Test
@Test
boolean isStatic;
if (f != null) {
f = null;
if (isGetter)
switch (testMode0) {
case TEST_SETTER|
case TEST_SETTER|
case TEST_SETTER|
System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, mh != null);
if (isGetter) {
.changeReturnType(void.class)
if (isGetter) {
if (isStatic) {
if (ftype == int.class)
if (ftype == int.class)
if (isStatic) {
if (ftype == int.class)
if (ftype == int.class)
@Test
@Test
@Test
@Test
testArrayElementGetterSetter(false);
@Test
testArrayElementGetterSetter(true);
countTest(true);
if (verbosity > 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]");
if (testSetter) {
if (elemType == int.class)
else if (elemType == boolean.class)
if (!testSetter) {
if (elemType == int.class)
else if (elemType == boolean.class)
return model;
static class Callee {
@Test
if (CAN_SKIP_WORKING) return;
void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
@Test
@Test
if (CAN_SKIP_WORKING) return;
if (CAN_TEST_LIGHTLY) return;
public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
casStep++;
if (CAN_TEST_LIGHTLY) continue;
if (i + d >= inargs) continue;
c /= inargs;
if (CAN_TEST_LIGHTLY && outargs >= 3 && (reorder[0] == reorder[1] || reorder[1] == reorder[2])) continue;
return reorder;
countTest();
for (int j : reorder) {
System.out.println("*** failed permuteArguments "+Arrays.toString(reorder)+" types="+Arrays.asList(types));
@Test
if (CAN_SKIP_WORKING) return;
countTest();
switch (nargs) {
Object args2 = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length));
args1[pos] = ValueConversions.changeArrayType(arrayType, Arrays.copyOfRange(args, pos, args.length));
} else if (argType == int.class) {
} else if (argType == long.class) {
@Test
if (CAN_SKIP_WORKING) return;
countTest();
@Test
if (CAN_SKIP_WORKING) return;
countTest();
@Test
if (CAN_SKIP_WORKING) return;
List.class,
CharSequence.class,
String.class }) {
countTest();
System.out.println("*** fail at n/rt = "+nargs+"/"+rtype.getSimpleName()+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
@Test
if (CAN_SKIP_WORKING) return;
countTest();
System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
@Test
if (CAN_SKIP_WORKING) return;
countTest();
System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result+" != "+expected);
@Test
if (CAN_SKIP_WORKING) return;
countTest();
// System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
@Test
if (CAN_SKIP_WORKING) return;
else if (argType == void.class)
countTest();
countTest();
switch (nargs) {
countTest();
countTest();
assertEquals(x, y);
assertEquals(x, y);
@Test
if (CAN_SKIP_WORKING) return;
countTest();
MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class));
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs1));
MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs1));
boolean equals;
switch (nargs) {
@Test
if (CAN_SKIP_WORKING) return;
static final int THROW_NOTHING = 0, THROW_CAUGHT = 1, THROW_UNCAUGHT = 2, THROW_THROUGH_ADAPTER = 3, THROW_MODE_LIMIT = 4;
void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs) throws Throwable {
private static <T extends Throwable>
throw exception;
return normal;
private int fakeIdentityCount;
void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs, int catchDrops) throws Throwable {
countTest();
System.out.println("catchException rt="+returnType+" throw="+throwMode+" nargs="+nargs+" drops="+catchDrops);
@Test
if (CAN_SKIP_WORKING) return;
countTest();
@Test
for (Class<?> ctype : new Class<?>[]{ Object.class, String.class, CharSequence.class, Number.class, Iterable.class}) {
System.out.println("*** testInterfaceCast: "+mh+" was "+mt+" => "+res+(docast ? " (explicitCastArguments)" : ""));
if (!sawFail) {
@Test
if (CAN_SKIP_WORKING) return;
static class Surprise {
countTest(false);
MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0;
assertEquals(x, y);
assertEquals(x, z);
assertEquals(x, y);
assertTrue(false);
return null;
@Test
if (CAN_SKIP_WORKING) return;
static void runForRunnable() {
public interface Fooable {
public interface WillThrow {
public void run();
@Test
if (CAN_SKIP_WORKING) return;
countTest();
countTest();
MethodHandle append = lookup.bind(appendResults, "add", MethodType.methodType(boolean.class, Object.class));
MethodHandle asList = lookup.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class));
MethodHandle mh = MethodHandles.filterReturnValue(asList, append).asVarargsCollector(Object[].class);
switch (l.size()) {
actual += l;
countTest();
new MyCheckedException()
countTest();
assertTrue(false);
String.class,
CharSequence.class,
PrivateRunnable.class,
Example.class }) {
countTest(false);
// not a public interface: test.java.lang.invoke.MethodHandlesTest$PrivateRunnable
// not a public interface: test.java.lang.invoke.MethodHandlesTest$Example
countTest(false);
@Test
if (CAN_SKIP_WORKING) return;
MethodHandle run = lookup.findStatic(lookup.lookupClass(), "runForRunnable", MethodType.methodType(void.class));
r.run();
Object o = r;
r = null;
boolean eq = (o == o);
class ValueConversions {
MethodType vaType = MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType));
throw err;
AS_LIST = IMPL_LOOKUP.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class));
class PackageSibling {