jdk-24/test/jdk/java/lang/invoke/lookup/ChainedLookupTest.java
Mandy Chung c6339cb8a2 8271820: Implementation of JEP 416: Reimplement Core Reflection with Method Handle
8013527: calling MethodHandles.lookup on itself leads to errors

Co-authored-by: Peter Levart <plevart@openjdk.org>
Co-authored-by: Claes Redestad <redestad@openjdk.org>
Co-authored-by: Mandy Chung <mchung@openjdk.org>
Reviewed-by: mcimadamore, plevart, egahlin, redestad, cjplummer, alanb
2021-10-28 18:32:50 +00:00

138 lines
5.2 KiB
Java

/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8013527
* @run testng/othervm ChainedLookupTest
* @summary Test MethodHandles.lookup method to produce the Lookup object with
* proper lookup class if invoked through reflection and method handle.
*/
import java.lang.invoke.*;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Method;
import org.testng.annotations.Test;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
import static org.testng.Assert.*;
public class ChainedLookupTest {
/**
* Direct call to MethodHandles::lookup
*/
@Test
public void staticLookup() throws Throwable {
Lookup lookup = lookup();
test(lookup, "Lookup produced via direct call to MethodHandles.lookup()");
}
/**
* Reflective Method::invoke on MethodHandles::lookup
*/
@Test
public void methodInvoke() throws Throwable {
Method m = MethodHandles.class.getMethod("lookup");
Lookup lookup = (Lookup) m.invoke(null);
test(lookup, "Lookup produced via reflective call");
}
/**
* Invoke Method::invoke on MethodHandles::lookup via MethodHandle
*/
@Test
public void methodInvokeViaMethodHandle() throws Throwable {
Method m = MethodHandles.class.getMethod("lookup");
MethodHandle mh = lookup().findVirtual(Method.class, "invoke",
methodType(Object.class, Object.class, Object[].class));
Lookup lookup = (Lookup)mh.invoke(m, (Object)null, (Object[])null);
test(lookup, "Lookup produced via Method::invoke via MethodHandle");
}
/**
* Invoke MethodHandle on MethodHandles::lookup via Method::invoke
*/
// @Test
public void methodHandleViaReflection() throws Throwable {
MethodHandle MH_lookup = lookup().findStatic(MethodHandles.class, "lookup", methodType(Lookup.class));
Lookup lookup = (Lookup) MH_lookup.invokeExact();
Method m = MethodHandle.class.getMethod("invoke", Object[].class);
// should this throw UnsupportedOperationException per MethodHandle::invoke spec?
lookup = (Lookup)m.invoke(MH_lookup);
test(lookup, "Lookup produced via MethodHandle::invoke via Method::invoke");
}
/**
* MethodHandle::invokeExact on MethodHandles::lookup
*/
@Test
public void methodHandle() throws Throwable {
MethodHandle MH_lookup = lookup().findStatic(MethodHandles.class, "lookup", methodType(Lookup.class));
Lookup lookup = (Lookup) MH_lookup.invokeExact();
test(lookup, "Lookup produced via MethodHandle");
}
/**
* MethodHandles::unreflect the reflective Method representing MethodHandles::lookup
*/
@Test
public void unreflect() throws Throwable {
MethodHandle MH_lookup = lookup().unreflect(MethodHandles.class.getMethod("lookup"));
Lookup lookup = (Lookup) MH_lookup.invokeExact();
test(lookup, "Lookup produced via unreflect MethodHandle");
}
/**
* Use the Lookup object returned from MethodHandle::invokeExact on MethodHandles::lookup
* to look up MethodHandle representing MethodHandles::lookup and then invoking it.
*/
@Test
public void chainedMethodHandle() throws Throwable {
MethodHandle MH_lookup = lookup().findStatic(MethodHandles.class, "lookup", methodType(Lookup.class));
Lookup lookup = (Lookup) MH_lookup.invokeExact();
MethodHandle MH_lookup2 = lookup.unreflect(MethodHandles.class.getMethod("lookup"));
Lookup lookup2 = (Lookup) MH_lookup2.invokeExact();
test(lookup2, "Lookup produced via a chained call to MethodHandle");
}
void test(Lookup lookup, String msg) throws Throwable {
assertTrue(lookup.lookupClass() == ChainedLookupTest.class);
assertTrue(lookup.hasFullPrivilegeAccess());
MethodHandle mh = lookup.findStatic(lookup.lookupClass(), "say", methodType(void.class, String.class));
mh.invokeExact(msg);
}
private static void say(String msg) {
System.out.println(msg);
}
}