mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8230501: Class data support for hidden classes
Reviewed-by: jvernee, psandoz, chegar
This commit is contained in:
parent
11dad148ff
commit
4356469a31
17 changed files with 946 additions and 139 deletions
|
@ -34,6 +34,7 @@ import sun.security.action.GetBooleanAction;
|
|||
|
||||
import java.io.FilePermission;
|
||||
import java.io.Serializable;
|
||||
import java.lang.constant.ConstantDescs;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
@ -55,7 +56,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
* @see LambdaMetafactory
|
||||
*/
|
||||
/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
|
||||
private static final int CLASSFILE_VERSION = 52;
|
||||
private static final int CLASSFILE_VERSION = 59;
|
||||
private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
|
||||
private static final String JAVA_LANG_OBJECT = "java/lang/Object";
|
||||
private static final String NAME_CTOR = "<init>";
|
||||
|
@ -71,12 +72,10 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
|
||||
private static final String NAME_METHOD_READ_OBJECT = "readObject";
|
||||
private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
|
||||
private static final String NAME_FIELD_IMPL_METHOD = "protectedImplMethod";
|
||||
|
||||
private static final String DESCR_CLASS = "Ljava/lang/Class;";
|
||||
private static final String DESCR_STRING = "Ljava/lang/String;";
|
||||
private static final String DESCR_OBJECT = "Ljava/lang/Object;";
|
||||
private static final String DESCR_METHOD_HANDLE = "Ljava/lang/invoke/MethodHandle;";
|
||||
private static final String DESCR_CTOR_SERIALIZED_LAMBDA
|
||||
= "(" + DESCR_CLASS + DESCR_STRING + DESCR_STRING + DESCR_STRING + "I"
|
||||
+ DESCR_STRING + DESCR_STRING + DESCR_STRING + DESCR_STRING + "[" + DESCR_OBJECT + ")V";
|
||||
|
@ -94,6 +93,9 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
|
||||
private static final boolean disableEagerInitialization;
|
||||
|
||||
// condy to load implMethod from class data
|
||||
private static final ConstantDynamic implMethodCondy;
|
||||
|
||||
static {
|
||||
final String dumpProxyClassesKey = "jdk.internal.lambda.dumpProxyClasses";
|
||||
String dumpPath = GetPropertyAction.privilegedGetProperty(dumpProxyClassesKey);
|
||||
|
@ -101,6 +103,12 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
|
||||
final String disableEagerInitializationKey = "jdk.internal.lambda.disableEagerInitialization";
|
||||
disableEagerInitialization = GetBooleanAction.privilegedGetProperty(disableEagerInitializationKey);
|
||||
|
||||
// condy to load implMethod from class data
|
||||
MethodType classDataMType = MethodType.methodType(Object.class, MethodHandles.Lookup.class, String.class, Class.class);
|
||||
Handle classDataBsm = new Handle(H_INVOKESTATIC, Type.getInternalName(MethodHandles.class), "classData",
|
||||
classDataMType.descriptorString(), false);
|
||||
implMethodCondy = new ConstantDynamic(ConstantDescs.DEFAULT_NAME, MethodHandle.class.descriptorString(), classDataBsm);
|
||||
}
|
||||
|
||||
// See context values in AbstractValidatingLambdaMetafactory
|
||||
|
@ -361,14 +369,6 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
}
|
||||
}
|
||||
|
||||
if (useImplMethodHandle) {
|
||||
FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_STATIC,
|
||||
NAME_FIELD_IMPL_METHOD,
|
||||
DESCR_METHOD_HANDLE,
|
||||
null, null);
|
||||
fv.visitEnd();
|
||||
}
|
||||
|
||||
if (isSerializable)
|
||||
generateSerializationFriendlyMethods();
|
||||
else if (accidentallySerializable)
|
||||
|
@ -394,7 +394,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
}
|
||||
try {
|
||||
// this class is linked at the indy callsite; so define a hidden nestmate
|
||||
Lookup lookup = caller.defineHiddenClass(classBytes, !disableEagerInitialization, NESTMATE, STRONG);
|
||||
Lookup lookup;
|
||||
if (useImplMethodHandle) {
|
||||
// If the target class invokes a method reference this::m which is
|
||||
// resolved to a protected method inherited from a superclass in a different
|
||||
|
@ -403,8 +403,10 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
// This lambda proxy class has no access to the resolved method.
|
||||
// So this workaround by passing the live implMethod method handle
|
||||
// to the proxy class to invoke directly.
|
||||
MethodHandle mh = lookup.findStaticSetter(lookup.lookupClass(), NAME_FIELD_IMPL_METHOD, MethodHandle.class);
|
||||
mh.invokeExact(implMethod);
|
||||
lookup = caller.defineHiddenClassWithClassData(classBytes, implMethod, !disableEagerInitialization,
|
||||
NESTMATE, STRONG);
|
||||
} else {
|
||||
lookup = caller.defineHiddenClass(classBytes, !disableEagerInitialization, NESTMATE, STRONG);
|
||||
}
|
||||
return lookup.lookupClass();
|
||||
} catch (IllegalAccessException e) {
|
||||
|
@ -554,8 +556,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
|||
visitInsn(DUP);
|
||||
}
|
||||
if (useImplMethodHandle) {
|
||||
visitVarInsn(ALOAD, 0);
|
||||
visitFieldInsn(GETSTATIC, lambdaClassName, NAME_FIELD_IMPL_METHOD, DESCR_METHOD_HANDLE);
|
||||
visitLdcInsn(implMethodCondy);
|
||||
}
|
||||
for (int i = 0; i < argNames.length; i++) {
|
||||
visitVarInsn(ALOAD, 0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue