diff --git a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 36ff5debbfc..6254e582c37 100644 --- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -23,6 +23,12 @@ * questions. */ +/* + * =========================================================================== + * (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved + * =========================================================================== + */ + package java.lang.invoke; import jdk.internal.org.objectweb.asm.*; @@ -163,7 +169,16 @@ public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, implMethodName = implInfo.getName(); implMethodDesc = implInfo.getMethodType().toMethodDescriptorString(); constructorType = invokedType.changeReturnType(Void.TYPE); - lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet(); + int uniqueID = targetClass.getName().hashCode() + ^ invokedType.toString().hashCode() + ^ samMethodName.hashCode() + ^ samMethodType.toString().hashCode() + ^ instantiatedMethodType.toString().hashCode() + ^ implMethodClassName.hashCode() + ^ implMethodName.hashCode() + ^ implMethodDesc.hashCode(); + uniqueID &= 0x7fffffff; + lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + uniqueID; cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); int parameterCount = invokedType.parameterCount(); if (parameterCount > 0) { @@ -252,6 +267,10 @@ public Constructor[] run() { * is not found */ private Class spinInnerClass() throws LambdaConversionException { + Class innerClass = MethodHandleNatives.findInSCC(lambdaClassName, targetClass); + if (innerClass != null) { + return innerClass; + } String[] interfaces; String samIntf = samBase.getName().replace('.', '/'); boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase); diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 2ff3cab04a4..0c08b980d9e 100644 --- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -23,6 +23,13 @@ * questions. */ +/* + * =========================================================================== + * (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved + * =========================================================================== + */ + + package java.lang.invoke; import jdk.internal.org.objectweb.asm.ClassWriter; @@ -38,6 +45,9 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.invoke.LambdaForm.BasicType; +import java.lang.invoke.LambdaForm.Name; +import java.lang.invoke.LambdaForm.NamedFunction; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; @@ -111,7 +121,12 @@ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize, if (DUMP_CLASS_FILES) { className = makeDumpableClassName(className); } - this.className = className; + int uniqueID = lambdaForm.toString().hashCode() + ^ className.hashCode() + ^ invokerName.hashCode() + ^ invokerType.toString().hashCode(); + uniqueID &= 0x7fffffff; + this.className = className + "$" + uniqueID; this.lambdaForm = lambdaForm; this.invokerName = invokerName; this.invokerType = invokerType; @@ -690,6 +705,10 @@ static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType if (pregenerated != null) return pregenerated; // pre-generated bytecode InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType); + Class customized = MethodHandleNatives.findInSCC(CLASS_PREFIX + g.className, HOST_CLASS); + if (customized != null) { + return resolveInvokerMember(customized, g.invokerName, g.invokerType); + } return g.loadMethod(g.generateCustomizedCodeBytes()); } @@ -1766,6 +1785,10 @@ static MemberName generateLambdaFormInterpreterEntryPoint(MethodType mt) { MethodType type = mt; // includes leading argument type = type.changeParameterType(0, MethodHandle.class); InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("LFI", name, type); + Class customized = MethodHandleNatives.findInSCC(CLASS_PREFIX + g.className, HOST_CLASS); + if (customized != null) { + return resolveInvokerMember(customized, g.invokerName, g.invokerType); + } return g.loadMethod(g.generateLambdaFormInterpreterEntryPointBytes()); } @@ -1825,6 +1848,10 @@ static MemberName generateNamedFunctionInvoker(MethodTypeForm typeForm) { MethodType invokerType = NamedFunction.INVOKER_METHOD_TYPE; String invokerName = "invoke_" + shortenSignature(basicTypeSignature(typeForm.erasedType())); InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("NFI", invokerName, invokerType); + Class customized = MethodHandleNatives.findInSCC(CLASS_PREFIX + g.className, HOST_CLASS); + if (customized != null) { + return resolveInvokerMember(customized, g.invokerName, g.invokerType); + } return g.loadMethod(g.generateNamedFunctionInvokerImpl(typeForm)); } diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java index 3e872414b6c..b1f7bc463b2 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -23,6 +23,12 @@ * questions. */ +/* + * =========================================================================== + * (c) Copyright IBM Corp. 2024, 2024 All Rights Reserved + * =========================================================================== + */ + package java.lang.invoke; import jdk.internal.ref.CleanerFactory; @@ -49,6 +55,7 @@ private MethodHandleNatives() { } // static only static native void init(MemberName self, Object ref); static native void expand(MemberName self); + static native Class findInSCC(String classname, Class hostClass); static native MemberName resolve(MemberName self, Class caller, boolean speculativeResolve) throws LinkageError, ClassNotFoundException; static native int getMembers(Class defc, String matchName, String matchSig,