< 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 >