8230501: Class data support for hidden classes

Reviewed-by: jvernee, psandoz, chegar
This commit is contained in:
Mandy Chung 2020-12-01 00:24:40 +00:00
parent 11dad148ff
commit 4356469a31
17 changed files with 946 additions and 139 deletions

View file

@ -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);