< prev index next > src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
Print this page
import java.lang.reflect.Modifier;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
+ import java.util.function.Function;
import static java.lang.classfile.ClassFile.*;
import java.lang.classfile.attribute.ExceptionsAttribute;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import static java.lang.constant.ConstantDescs.*;
import static java.lang.invoke.MethodHandleNatives.Constants.NESTMATE_CLASS;
import static java.lang.invoke.MethodHandleNatives.Constants.STRONG_LOADER_LINK;
+ import java.util.ArrayList;
import jdk.internal.constant.ConstantUtils;
import jdk.internal.constant.MethodTypeDescImpl;
import jdk.internal.vm.annotation.Stable;
import sun.invoke.util.Wrapper;
* types must extend {@code Serializable}.
* @param altInterfaces Additional interfaces which the lambda object
* should implement.
* @param altMethods Method types for additional signatures to be
* implemented by invoking the implementation method
+ * @param finisher Function called at the end of the lambda class build process
+ * that returns an additional object to append to the class data,
+ * may be (@code null}, may return {@code null}.
* @throws LambdaConversionException If any of the meta-factory protocol
* invariants are violated
*/
public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
MethodType factoryType,
MethodType interfaceMethodType,
MethodHandle implementation,
MethodType dynamicMethodType,
boolean isSerializable,
Class<?>[] altInterfaces,
- MethodType[] altMethods)
+ MethodType[] altMethods,
+ Function<ClassBuilder, Object> finisher)
throws LambdaConversionException {
super(caller, factoryType, interfaceMethodName, interfaceMethodType,
implementation, dynamicMethodType,
- isSerializable, altInterfaces, altMethods);
+ isSerializable, altInterfaces, altMethods, finisher);
implMethodClassDesc = implClassDesc(implClass);
implMethodName = implInfo.getName();
implMethodDesc = methodDesc(implInfo.getMethodType());
constructorType = factoryType.changeReturnType(Void.TYPE);
lambdaClassName = lambdaClassName(targetClass);
accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(i);
}
interfaces = List.copyOf(itfs);
}
final boolean finalAccidentallySerializable = accidentallySerializable;
+ final Object[] additionalClassDataHolder = new Object[1];
final byte[] classBytes = ClassFile.of().build(lambdaClassEntry, pool, new Consumer<ClassBuilder>() {
@Override
public void accept(ClassBuilder clb) {
clb.withFlags(ACC_SUPER | ACC_FINAL | ACC_SYNTHETIC)
.withInterfaceSymbols(interfaces);
if (isSerializable)
generateSerializationFriendlyMethods(clb);
else if (finalAccidentallySerializable)
generateSerializationHostileMethods(clb);
+
+ if (finisher != null) {
+ additionalClassDataHolder[0] = finisher.apply(clb);
+ }
}
});
// Define the generated class in this VM.
try {
// this class is linked at the indy callsite; so define a hidden nestmate
- var classdata = useImplMethodHandle? implementation : null;
+ var additionalClassData = additionalClassDataHolder[0];
+ var classdata = additionalClassData == null
+ ? useImplMethodHandle ? List.of(implementation) : null
+ : useImplMethodHandle ? List.of(implementation, additionalClassData) : List.of(additionalClassData);
return caller.makeHiddenClassDefiner(lambdaClassName, classBytes, lambdaProxyClassFileDumper, NESTMATE_CLASS | STRONG_LOADER_LINK)
.defineClass(!disableEagerInitialization, classdata);
} catch (Throwable t) {
throw new InternalError(t);
cob.new_(implMethodClassDesc)
.dup();
}
if (useImplMethodHandle) {
ConstantPoolBuilder cp = cob.constantPool();
- cob.ldc(cp.constantDynamicEntry(cp.bsmEntry(cp.methodHandleEntry(BSM_CLASS_DATA), List.of()),
+ cob.ldc(cp.constantDynamicEntry(cp.bsmEntry(cp.methodHandleEntry(BSM_CLASS_DATA_AT), List.of(cp.intEntry(0))),
cp.nameAndTypeEntry(DEFAULT_NAME, CD_MethodHandle)));
}
for (int i = 0; i < argDescs.length; i++) {
cob.aload(0)
.getfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argName(i), argDescs[i])));
< prev index next >