src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
Print this page
rev 9538 : generates MH link to static factory for lambdas
rev 9539 : fix bytecode loading constructor parameters
rev 9540 : whitespace cleaning
@@ -47,10 +47,11 @@
private static final int CLASSFILE_VERSION = 51;
private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
private static final String NAME_MAGIC_ACCESSOR_IMPL = "java/lang/invoke/MagicLambdaImpl";
private static final String NAME_CTOR = "<init>";
+ private static final String NAME_FACTORY = "get$Lambda";
//Serialization support
private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
@@ -190,13 +191,11 @@
});
Object inst = ctrs[0].newInstance();
return new ConstantCallSite(MethodHandles.constant(samBase, inst));
} else {
return new ConstantCallSite(
- MethodHandles.Lookup.IMPL_LOOKUP
- .findConstructor(innerClass, constructorType)
- .asType(constructorType.changeReturnType(samBase)));
+ MethodHandles.Lookup.IMPL_LOOKUP.findStatic(innerClass, NAME_FACTORY, invokedType));
}
}
/**
* Generate a class file which implements the functional
@@ -232,10 +231,14 @@
fv.visitEnd();
}
generateConstructor();
+ if (invokedType.parameterCount() != 0) {
+ generateFactory();
+ }
+
// Forward the SAM method
String methodDescriptor = samMethodType.toMethodDescriptorString();
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
methodDescriptor, null, null);
new ForwardingMethodGenerator(mv).generate(methodDescriptor);
@@ -287,10 +290,28 @@
classBytes, 0, classBytes.length,
loader, pd);
}
/**
+ * 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);
+ for (int typeIndex = 0, varIndex = 0; typeIndex < argTypes.length; typeIndex++) {
+ m.visitVarInsn(argTypes[typeIndex].getOpcode(ILOAD), varIndex);
+ varIndex += argTypes[typeIndex].getSize();
+ }
+ m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorDesc);
+ m.visitInsn(ARETURN);
+ m.visitMaxs(-1, -1);
+ m.visitEnd();
+ }
+
+ /**
* Generate the constructor for the class
*/
private void generateConstructor() {
// Generate constructor
MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,