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
This commit is contained in:
Mandy Chung 2021-10-28 18:32:50 +00:00
parent 5a768f75c9
commit c6339cb8a2
78 changed files with 6118 additions and 544 deletions

View file

@ -26,7 +26,9 @@
package java.lang.reflect;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.VM;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.CallerSensitiveAdapter;
import jdk.internal.reflect.MethodAccessor;
import jdk.internal.reflect.Reflection;
import jdk.internal.vm.annotation.ForceInline;
@ -67,24 +69,22 @@ import java.util.StringJoiner;
* @since 1.1
*/
public final class Method extends Executable {
@Stable
private Class<?> clazz;
private int slot;
private final Class<?> clazz;
private final int slot;
// This is guaranteed to be interned by the VM in the 1.4
// reflection implementation
private String name;
private Class<?> returnType;
private Class<?>[] parameterTypes;
private Class<?>[] exceptionTypes;
@Stable
private int modifiers;
private final String name;
private final Class<?> returnType;
private final Class<?>[] parameterTypes;
private final Class<?>[] exceptionTypes;
private final int modifiers;
// Generics and annotations support
private transient String signature;
private final transient String signature;
// generic info repository; lazily initialized
private transient MethodRepository genericInfo;
private byte[] annotations;
private byte[] parameterAnnotations;
private byte[] annotationDefault;
private final byte[] annotations;
private final byte[] parameterAnnotations;
private final byte[] annotationDefault;
@Stable
private MethodAccessor methodAccessor;
// For sharing of MethodAccessors. This branching structure is
@ -553,20 +553,64 @@ public final class Method extends Executable {
@ForceInline // to ensure Reflection.getCallerClass optimization
@IntrinsicCandidate
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
throws IllegalAccessException, InvocationTargetException
{
boolean callerSensitive = isCallerSensitive();
Class<?> caller = null;
if (!override || callerSensitive) {
caller = Reflection.getCallerClass();
}
// Reflection::getCallerClass filters all subclasses of
// jdk.internal.reflect.MethodAccessorImpl and Method::invoke(Object, Object[])
// Should not call Method::invoke(Object, Object[], Class) here
if (!override) {
checkAccess(caller, clazz,
Modifier.isStatic(modifiers) ? null : obj.getClass(),
modifiers);
}
MethodAccessor ma = methodAccessor; // read @Stable
if (ma == null) {
ma = acquireMethodAccessor();
}
return callerSensitive ? ma.invoke(obj, args, caller) : ma.invoke(obj, args);
}
/**
* This is to support MethodHandle calling caller-sensitive Method::invoke
* that may invoke a caller-sensitive method in order to get the original caller
* class (not the injected invoker).
*
* If this adapter is not presented, MethodHandle invoking Method::invoke
* will get an invoker class, a hidden nestmate of the original caller class,
* that becomes the caller class invoking Method::invoke.
*/
@CallerSensitiveAdapter
private Object invoke(Object obj, Object[] args, Class<?> caller)
throws IllegalAccessException, InvocationTargetException
{
boolean callerSensitive = isCallerSensitive();
if (!override) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz,
Modifier.isStatic(modifiers) ? null : obj.getClass(),
modifiers);
}
MethodAccessor ma = methodAccessor; // read volatile
MethodAccessor ma = methodAccessor; // read @Stable
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
return callerSensitive ? ma.invoke(obj, args, caller) : ma.invoke(obj, args);
}
@Stable private Boolean callerSensitive; // lazily initialize
private boolean isCallerSensitive() {
Boolean cs = callerSensitive;
if (cs == null) {
callerSensitive = cs = Reflection.isCallerSensitive(this);
}
return cs;
}
/**
@ -672,8 +716,10 @@ public final class Method extends Executable {
methodAccessor = tmp;
} else {
// Otherwise fabricate one and propagate it up to the root
tmp = reflectionFactory.newMethodAccessor(this);
setMethodAccessor(tmp);
tmp = reflectionFactory.newMethodAccessor(this, isCallerSensitive());
// set the method accessor only if it's not using native implementation
if (VM.isJavaLangInvokeInited())
setMethodAccessor(tmp);
}
return tmp;