Skip to content

Commit c6339cb

Browse files
Mandy ChungPeter Levartcl4es
committed
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
1 parent 5a768f7 commit c6339cb

File tree

78 files changed

+6119
-545
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+6119
-545
lines changed

make/jdk/src/classes/build/tools/classlist/HelloClasslist.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ public static void main(String ... args) throws Throwable {
116116
DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.ROOT)
117117
.format(new Date()));
118118

119+
// A selection of trivial and common reflection operations
120+
var instance = HelloClasslist.class.getConstructor().newInstance();
121+
HelloClasslist.class.getMethod("staticMethod_V").invoke(null);
122+
var obj = HelloClasslist.class.getMethod("staticMethod_L_L", Object.class).invoke(null, instance);
123+
HelloClasslist.class.getField("field").get(instance);
124+
119125
// A selection of trivial and relatively common MH operations
120126
invoke(MethodHandles.identity(double.class), 1.0);
121127
invoke(MethodHandles.identity(int.class), 1);
@@ -126,8 +132,14 @@ public static void main(String ... args) throws Throwable {
126132
LOGGER.log(Level.FINE, "New Date: " + newDate + " - old: " + oldDate);
127133
}
128134

135+
public HelloClasslist() {}
136+
137+
public String field = "someValue";
138+
129139
public static void staticMethod_V() {}
130140

141+
public static Object staticMethod_L_L(Object o) { return o; }
142+
131143
private static MethodHandle handle(String name, MethodType type) throws Throwable {
132144
return MethodHandles.lookup().findStatic(HelloClasslist.class, name, type);
133145
}

src/hotspot/share/ci/ciField.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
224224
return false;
225225
// Even if general trusting is disabled, trust system-built closures in these packages.
226226
if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke") ||
227+
holder->is_in_package("java/lang/reflect") || holder->is_in_package("jdk/internal/reflect") ||
227228
holder->is_in_package("jdk/internal/foreign") || holder->is_in_package("jdk/incubator/foreign") ||
228229
holder->is_in_package("jdk/internal/vm/vector") || holder->is_in_package("jdk/incubator/vector") ||
229230
holder->is_in_package("java/lang"))

src/java.base/share/classes/java/lang/Class.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import jdk.internal.misc.Unsafe;
7474
import jdk.internal.module.Resources;
7575
import jdk.internal.reflect.CallerSensitive;
76+
import jdk.internal.reflect.CallerSensitiveAdapter;
7677
import jdk.internal.reflect.ConstantPool;
7778
import jdk.internal.reflect.Reflection;
7879
import jdk.internal.reflect.ReflectionFactory;
@@ -372,9 +373,15 @@ static String typeVarBounds(TypeVariable<?> typeVar) {
372373
public static Class<?> forName(String className)
373374
throws ClassNotFoundException {
374375
Class<?> caller = Reflection.getCallerClass();
375-
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
376+
return forName(className, caller);
376377
}
377378

379+
// Caller-sensitive adapter method for reflective invocation
380+
@CallerSensitiveAdapter
381+
private static Class<?> forName(String className, Class<?> caller)
382+
throws ClassNotFoundException {
383+
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
384+
}
378385

379386
/**
380387
* Returns the {@code Class} object associated with the class or
@@ -456,11 +463,25 @@ public static Class<?> forName(String name, boolean initialize,
456463
// Reflective call to get caller class is only needed if a security manager
457464
// is present. Avoid the overhead of making this call otherwise.
458465
caller = Reflection.getCallerClass();
466+
}
467+
return forName(name, initialize, loader, caller);
468+
}
469+
470+
// Caller-sensitive adapter method for reflective invocation
471+
@CallerSensitiveAdapter
472+
private static Class<?> forName(String name, boolean initialize, ClassLoader loader, Class<?> caller)
473+
throws ClassNotFoundException
474+
{
475+
@SuppressWarnings("removal")
476+
SecurityManager sm = System.getSecurityManager();
477+
if (sm != null) {
478+
// Reflective call to get caller class is only needed if a security manager
479+
// is present. Avoid the overhead of making this call otherwise.
459480
if (loader == null) {
460481
ClassLoader ccl = ClassLoader.getClassLoader(caller);
461482
if (ccl != null) {
462483
sm.checkPermission(
463-
SecurityConstants.GET_CLASSLOADER_PERMISSION);
484+
SecurityConstants.GET_CLASSLOADER_PERMISSION);
464485
}
465486
}
466487
}
@@ -523,13 +544,24 @@ private static native Class<?> forName0(String name, boolean initialize,
523544
@SuppressWarnings("removal")
524545
@CallerSensitive
525546
public static Class<?> forName(Module module, String name) {
547+
Class<?> caller = null;
548+
SecurityManager sm = System.getSecurityManager();
549+
if (sm != null) {
550+
caller = Reflection.getCallerClass();
551+
}
552+
return forName(module, name, caller);
553+
}
554+
555+
// Caller-sensitive adapter method for reflective invocation
556+
@SuppressWarnings("removal")
557+
@CallerSensitiveAdapter
558+
private static Class<?> forName(Module module, String name, Class<?> caller) {
526559
Objects.requireNonNull(module);
527560
Objects.requireNonNull(name);
528561

529562
ClassLoader cl;
530563
SecurityManager sm = System.getSecurityManager();
531564
if (sm != null) {
532-
Class<?> caller = Reflection.getCallerClass();
533565
if (caller != null && caller.getModule() != module) {
534566
// if caller is null, Class.forName is the last java frame on the stack.
535567
// java.base has all permissions

src/java.base/share/classes/java/lang/ClassLoader.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
import jdk.internal.misc.Unsafe;
6565
import jdk.internal.misc.VM;
6666
import jdk.internal.reflect.CallerSensitive;
67+
import jdk.internal.reflect.CallerSensitiveAdapter;
6768
import jdk.internal.reflect.Reflection;
6869
import jdk.internal.util.StaticProperty;
6970
import sun.reflect.misc.ReflectUtil;
@@ -1615,9 +1616,13 @@ protected Enumeration<URL> findResources(String name) throws IOException {
16151616
*/
16161617
@CallerSensitive
16171618
protected static boolean registerAsParallelCapable() {
1618-
Class<? extends ClassLoader> callerClass =
1619-
Reflection.getCallerClass().asSubclass(ClassLoader.class);
1620-
return ParallelLoaders.register(callerClass);
1619+
return registerAsParallelCapable(Reflection.getCallerClass());
1620+
}
1621+
1622+
// Caller-sensitive adapter method for reflective invocation
1623+
@CallerSensitiveAdapter
1624+
private static boolean registerAsParallelCapable(Class<?> caller) {
1625+
return ParallelLoaders.register(caller.asSubclass(ClassLoader.class));
16211626
}
16221627

16231628
/**

src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
package java.lang.invoke;
2727

2828
import jdk.internal.misc.CDS;
29-
import jdk.internal.misc.VM;
3029
import jdk.internal.org.objectweb.asm.*;
3130
import sun.invoke.util.BytecodeDescriptor;
3231
import sun.invoke.util.VerifyAccess;
@@ -37,7 +36,6 @@
3736
import java.io.Serializable;
3837
import java.lang.constant.ConstantDescs;
3938
import java.lang.invoke.MethodHandles.Lookup;
40-
import java.lang.reflect.Constructor;
4139
import java.lang.reflect.Modifier;
4240
import java.security.AccessController;
4341
import java.security.PrivilegedAction;
@@ -46,8 +44,10 @@
4644
import java.util.PropertyPermission;
4745
import java.util.Set;
4846

47+
import static java.lang.invoke.MethodHandleStatics.CLASSFILE_VERSION;
4948
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
5049
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG;
50+
import static java.lang.invoke.MethodType.methodType;
5151
import static jdk.internal.org.objectweb.asm.Opcodes.*;
5252

5353
/**
@@ -57,7 +57,6 @@
5757
* @see LambdaMetafactory
5858
*/
5959
/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
60-
private static final int CLASSFILE_VERSION = VM.classFileVersion();
6160
private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
6261
private static final String JAVA_LANG_OBJECT = "java/lang/Object";
6362
private static final String NAME_CTOR = "<init>";
@@ -106,7 +105,7 @@
106105
disableEagerInitialization = GetBooleanAction.privilegedGetProperty(disableEagerInitializationKey);
107106

108107
// condy to load implMethod from class data
109-
MethodType classDataMType = MethodType.methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class);
108+
MethodType classDataMType = methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class);
110109
Handle classDataBsm = new Handle(H_INVOKESTATIC, Type.getInternalName(MethodHandles.class), "classData",
111110
classDataMType.descriptorString(), false);
112111
implMethodCondy = new ConstantDynamic(ConstantDescs.DEFAULT_NAME, MethodHandle.class.descriptorString(), classDataBsm);
@@ -227,50 +226,28 @@ private static String lambdaClassName(Class<?> targetClass) {
227226
@Override
228227
CallSite buildCallSite() throws LambdaConversionException {
229228
final Class<?> innerClass = spinInnerClass();
230-
if (factoryType.parameterCount() == 0) {
231-
// In the case of a non-capturing lambda, we optimize linkage by pre-computing a single instance,
232-
// unless we've suppressed eager initialization
233-
if (disableEagerInitialization) {
234-
try {
235-
return new ConstantCallSite(caller.findStaticGetter(innerClass, LAMBDA_INSTANCE_FIELD,
236-
factoryType.returnType()));
237-
} catch (ReflectiveOperationException e) {
238-
throw new LambdaConversionException(
239-
"Exception finding " + LAMBDA_INSTANCE_FIELD + " static field", e);
240-
}
241-
} else {
242-
@SuppressWarnings("removal")
243-
final Constructor<?>[] ctrs = AccessController.doPrivileged(
244-
new PrivilegedAction<>() {
245-
@Override
246-
public Constructor<?>[] run() {
247-
Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
248-
if (ctrs.length == 1) {
249-
// The lambda implementing inner class constructor is private, set
250-
// it accessible (by us) before creating the constant sole instance
251-
ctrs[0].setAccessible(true);
252-
}
253-
return ctrs;
254-
}
255-
});
256-
if (ctrs.length != 1) {
257-
throw new LambdaConversionException("Expected one lambda constructor for "
258-
+ innerClass.getCanonicalName() + ", got " + ctrs.length);
259-
}
260-
261-
try {
262-
Object inst = ctrs[0].newInstance();
263-
return new ConstantCallSite(MethodHandles.constant(interfaceClass, inst));
264-
} catch (ReflectiveOperationException e) {
265-
throw new LambdaConversionException("Exception instantiating lambda object", e);
266-
}
229+
if (factoryType.parameterCount() == 0 && disableEagerInitialization) {
230+
try {
231+
return new ConstantCallSite(caller.findStaticGetter(innerClass, LAMBDA_INSTANCE_FIELD,
232+
factoryType.returnType()));
233+
} catch (ReflectiveOperationException e) {
234+
throw new LambdaConversionException(
235+
"Exception finding " + LAMBDA_INSTANCE_FIELD + " static field", e);
267236
}
268237
} else {
269238
try {
270239
MethodHandle mh = caller.findConstructor(innerClass, constructorType);
271-
return new ConstantCallSite(mh.asType(factoryType));
240+
if (factoryType.parameterCount() == 0) {
241+
// In the case of a non-capturing lambda, we optimize linkage by pre-computing a single instance
242+
Object inst = mh.asType(methodType(Object.class)).invokeExact();
243+
return new ConstantCallSite(MethodHandles.constant(interfaceClass, inst));
244+
} else {
245+
return new ConstantCallSite(mh.asType(factoryType));
246+
}
272247
} catch (ReflectiveOperationException e) {
273248
throw new LambdaConversionException("Exception finding constructor", e);
249+
} catch (Throwable e) {
250+
throw new LambdaConversionException("Exception instantiating lambda object", e);
274251
}
275252
}
276253
}

src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import java.util.Arrays;
4545
import java.util.HashMap;
4646
import java.util.List;
47+
import java.util.Set;
4748
import java.util.stream.Stream;
4849

4950
import static java.lang.invoke.LambdaForm.BasicType;
@@ -316,7 +317,7 @@ private static String debugString(Object arg) {
316317
* Extract the MemberName of a newly-defined method.
317318
*/
318319
private MemberName loadMethod(byte[] classFile) {
319-
Class<?> invokerClass = LOOKUP.makeHiddenClassDefiner(className, classFile)
320+
Class<?> invokerClass = LOOKUP.makeHiddenClassDefiner(className, classFile, Set.of())
320321
.defineClass(true, classDataValues());
321322
return resolveInvokerMember(invokerClass, invokerName, invokerType);
322323
}
@@ -376,7 +377,7 @@ static void clinit(ClassWriter cw, String className, List<ClassData> classData)
376377
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
377378
mv.visitCode();
378379
mv.visitLdcInsn(Type.getType("L" + className + ";"));
379-
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/invoke/MethodHandleNatives",
380+
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/invoke/MethodHandles",
380381
"classData", "(Ljava/lang/Class;)Ljava/lang/Object;", false);
381382
// we should optimize one single element case that does not need to create a List
382383
mv.visitTypeInsn(Opcodes.CHECKCAST, "java/util/List");

0 commit comments

Comments
 (0)