< prev index next >

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

Print this page

        

*** 55,64 **** --- 55,65 ---- /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { 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 = "<init>"; + private static final String LAMBDA_INSTANCE_FIELD = "LAMBDA_INSTANCE$"; //Serialization support private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda"; private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException"; private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
*** 204,216 **** * is not found */ @Override CallSite buildCallSite() throws LambdaConversionException { final Class<?> innerClass = spinInnerClass(); ! 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 final Constructor<?>[] ctrs = AccessController.doPrivileged( new PrivilegedAction<>() { @Override public Constructor<?>[] run() { Constructor<?>[] ctrs = innerClass.getDeclaredConstructors(); --- 205,224 ---- * is not found */ @Override CallSite buildCallSite() throws LambdaConversionException { final Class<?> innerClass = spinInnerClass(); ! if (invokedType.parameterCount() == 0) { // In the case of a non-capturing lambda, we optimize linkage by pre-computing a single instance, // unless we've suppressed eager initialization + if (disableEagerInitialization) { + try { + return new ConstantCallSite(caller.findStaticGetter(innerClass, LAMBDA_INSTANCE_FIELD, invokedType.returnType())); + } catch (ReflectiveOperationException e) { + throw new LambdaConversionException("Exception finding " + LAMBDA_INSTANCE_FIELD + " static field", e); + } + } else { final Constructor<?>[] ctrs = AccessController.doPrivileged( new PrivilegedAction<>() { @Override public Constructor<?>[] run() { Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
*** 231,240 **** --- 239,249 ---- Object inst = ctrs[0].newInstance(); return new ConstantCallSite(MethodHandles.constant(samBase, inst)); } catch (ReflectiveOperationException e) { throw new LambdaConversionException("Exception instantiating lambda object", e); } + } } else { try { MethodHandle mh = caller.findConstructor(innerClass, invokedType.changeReturnType(void.class)); return new ConstantCallSite(mh.asType(invokedType)); } catch (ReflectiveOperationException e) {
*** 329,338 **** --- 338,351 ---- fv.visitEnd(); } generateConstructor(); + if (invokedType.parameterCount() == 0 && disableEagerInitialization) { + generateClassInitializer(); + } + // Forward the SAM method MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName, samMethodType.toMethodDescriptorString(), null, null); new ForwardingMethodGenerator(mv).generate(samMethodType);
*** 397,406 **** --- 410,444 ---- throw new InternalError(t); } } /** + * Generate a static field and a static initializer that sets this field to an instance of the lambda + */ + private void generateClassInitializer() { + String lambdaTypeDescriptor = invokedType.returnType().descriptorString(); + + // Generate the static final field that holds the lambda singleton + FieldVisitor fv = cw.visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, LAMBDA_INSTANCE_FIELD, lambdaTypeDescriptor, null, null); + fv.visitEnd(); + + // Instantiate the lambda and store it to the static final field + MethodVisitor clinit = cw.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null); + clinit.visitCode(); + + clinit.visitTypeInsn(NEW, lambdaClassName); + clinit.visitInsn(Opcodes.DUP); + assert invokedType.parameterCount() == 0; + clinit.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false); + clinit.visitFieldInsn(PUTSTATIC, lambdaClassName, LAMBDA_INSTANCE_FIELD, lambdaTypeDescriptor); + + clinit.visitInsn(RETURN); + clinit.visitMaxs(-1, -1); + clinit.visitEnd(); + } + + /** * Generate the constructor for the class */ private void generateConstructor() { // Generate constructor MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,
< prev index next >