--- old/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java 2019-12-03 19:37:24.000000000 -0800 +++ new/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java 2019-12-03 19:37:24.000000000 -0800 @@ -27,12 +27,12 @@ import jdk.internal.org.objectweb.asm.*; import sun.invoke.util.BytecodeDescriptor; -import jdk.internal.misc.Unsafe; import sun.security.action.GetPropertyAction; import sun.security.action.GetBooleanAction; import java.io.FilePermission; import java.io.Serializable; +import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Constructor; import java.security.AccessController; import java.security.PrivilegedAction; @@ -41,6 +41,7 @@ import java.util.PropertyPermission; import java.util.Set; +import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE; import static jdk.internal.org.objectweb.asm.Opcodes.*; /** @@ -50,13 +51,10 @@ * @see LambdaMetafactory */ /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { - private static final Unsafe UNSAFE = Unsafe.getUnsafe(); - private static final int CLASSFILE_VERSION = 52; 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 = ""; - private static final String NAME_FACTORY = "get$Lambda"; //Serialization support private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda"; @@ -78,8 +76,6 @@ private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION = "(Ljava/lang/String;)V"; private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION}; - private static final String DESCR_HIDDEN = "Ljdk/internal/vm/annotation/Hidden;"; - private static final String[] EMPTY_STRING_ARRAY = new String[0]; // Used to ensure that each spun class name is unique @@ -163,7 +159,7 @@ implMethodName = implInfo.getName(); implMethodDesc = implInfo.getMethodType().toMethodDescriptorString(); constructorType = invokedType.changeReturnType(Void.TYPE); - lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet(); + lambdaClassName = lambdaClassName(targetClass); cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); int parameterCount = invokedType.parameterCount(); if (parameterCount > 0) { @@ -178,6 +174,15 @@ } } + private static String lambdaClassName(Class targetClass) { + String name = targetClass.getName(); + if (targetClass.isHiddenClass()) { + // use the original class name + name = name.replace('/', '_'); + } + return name.replace('.', '/') + "$$Lambda$" + counter.incrementAndGet(); + } + /** * Build the CallSite. Generate a class file which implements the functional * interface, define the class, if there are no parameters create an instance @@ -193,6 +198,7 @@ @Override CallSite buildCallSite() throws LambdaConversionException { final Class innerClass = spinInnerClass(); + assert innerClass.isHiddenClass() : innerClass.toString(); if (invokedType.parameterCount() == 0 && !disableEagerInitialization) { // In the case of a non-capturing lambda, we optimize linkage by pre-computing a single instance, // unless we've suppressed eager initialization @@ -217,20 +223,14 @@ try { Object inst = ctrs[0].newInstance(); return new ConstantCallSite(MethodHandles.constant(samBase, inst)); - } - catch (ReflectiveOperationException e) { + } catch (ReflectiveOperationException e) { throw new LambdaConversionException("Exception instantiating lambda object", e); } } else { try { - if (!disableEagerInitialization) { - UNSAFE.ensureClassInitialized(innerClass); - } - return new ConstantCallSite( - MethodHandles.Lookup.IMPL_LOOKUP - .findStatic(innerClass, NAME_FACTORY, invokedType)); - } - catch (ReflectiveOperationException e) { + MethodHandle mh = caller.findConstructor(innerClass, invokedType.changeReturnType(void.class)); + return new ConstantCallSite(mh.asType(invokedType)); + } catch (ReflectiveOperationException e) { throw new LambdaConversionException("Exception finding constructor", e); } } @@ -283,14 +283,9 @@ generateConstructor(); - if (invokedType.parameterCount() != 0 || disableEagerInitialization) { - generateFactory(); - } - // Forward the SAM method MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName, samMethodType.toMethodDescriptorString(), null, null); - mv.visitAnnotation(DESCR_HIDDEN, true); new ForwardingMethodGenerator(mv).generate(samMethodType); // Forward the bridges @@ -298,7 +293,6 @@ for (MethodType mt : additionalBridges) { mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName, mt.toMethodDescriptorString(), null, null); - mv.visitAnnotation(DESCR_HIDDEN, true); new ForwardingMethodGenerator(mv).generate(mt); } } @@ -313,7 +307,6 @@ // Define the generated class in this VM. final byte[] classBytes = cw.toByteArray(); - // If requested, dump out to a file for debugging purposes if (dumper != null) { AccessController.doPrivileged(new PrivilegedAction<>() { @@ -327,28 +320,12 @@ // createDirectories may need it new PropertyPermission("user.dir", "read")); } - - return UNSAFE.defineAnonymousClass(targetClass, classBytes, null); - } - - /** - * Generate the factory method for the class - */ - private void generateFactory() { - MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null); - m.visitCode(); - m.visitTypeInsn(NEW, lambdaClassName); - m.visitInsn(Opcodes.DUP); - int parameterCount = invokedType.parameterCount(); - for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) { - Class argType = invokedType.parameterType(typeIndex); - m.visitVarInsn(getLoadOpcode(argType), varIndex); - varIndex += getParameterSize(argType); - } - m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false); - m.visitInsn(ARETURN); - m.visitMaxs(-1, -1); - m.visitEnd(); + try { + // this class is linked at the indy callsite; so define a hidden nestmate + return caller.defineHiddenClass(classBytes, !disableEagerInitialization, NESTMATE).lookupClass(); + } catch (IllegalAccessException e) { + throw new LambdaConversionException("Exception defining lambda proxy class", e); + } } /**