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..3fdbb7417e2 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,29 @@ public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, implMethodName = implInfo.getName(); implMethodDesc = implInfo.getMethodType().toMethodDescriptorString(); constructorType = invokedType.changeReturnType(Void.TYPE); - lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet(); + String rawUniqueID = targetClass.getName() + + invokedType.toString() + + samMethodName + + samMethodType.toString() + + instantiatedMethodType.toString() + + implMethodClassName + + implMethodName + + implMethodDesc; + StringBuilder encodedUniqueID = new StringBuilder(); + String parentheses = "(){}[]<>"; + for (int i = 0; i < rawUniqueID.length(); i++) { + char currentChar = rawUniqueID.charAt(i); + if (Character.isLetterOrDigit(currentChar)) { + encodedUniqueID.append(currentChar); + } else { + if (parentheses.indexOf(currentChar) != -1) { + encodedUniqueID.append("__"); + } else { + encodedUniqueID.append('_'); + } + } + } + lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + encodedUniqueID.toString(); cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); int parameterCount = invokedType.parameterCount(); if (parameterCount > 0) { @@ -252,6 +280,10 @@ public Constructor[] run() { * is not found */ private Class spinInnerClass() throws LambdaConversionException { + Class innerClass = MethodHandleNatives.findLambdaInSCC(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..dc9ac295f42 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; @@ -111,7 +118,22 @@ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize, if (DUMP_CLASS_FILES) { className = makeDumpableClassName(className); } - this.className = className; + String rawUniqueID = className + invokerName + invokerType.toString() + lambdaForm.toString(); + StringBuilder encodedUniqueID = new StringBuilder(); + String parentheses = "(){}[]<>"; + for (int i = 0; i < rawUniqueID.length(); i++) { + char currentChar = rawUniqueID.charAt(i); + if (Character.isLetterOrDigit(currentChar)) { + encodedUniqueID.append(currentChar); + } else { + if (parentheses.indexOf(currentChar) != -1) { + encodedUniqueID.append("__"); + } else { + encodedUniqueID.append('_'); + } + } + } + this.className = className + "$" + encodedUniqueID.toString(); this.lambdaForm = lambdaForm; this.invokerName = invokerName; this.invokerType = invokerType; @@ -690,6 +712,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.findLambdaFormInSCC(CLASS_PREFIX + g.className, HOST_CLASS); + if (customized != null) { + return resolveInvokerMember(customized, g.invokerName, g.invokerType); + } return g.loadMethod(g.generateCustomizedCodeBytes()); } @@ -1766,6 +1792,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.findLambdaFormInSCC(CLASS_PREFIX + g.className, HOST_CLASS); + if (customized != null) { + return resolveInvokerMember(customized, g.invokerName, g.invokerType); + } return g.loadMethod(g.generateLambdaFormInterpreterEntryPointBytes()); } @@ -1825,6 +1855,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.findLambdaFormInSCC(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..4e2bf196b85 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,8 @@ private MethodHandleNatives() { } // static only static native void init(MemberName self, Object ref); static native void expand(MemberName self); + static native Class findLambdaFormInSCC(String classname, Class hostClass); + static native Class findLambdaInSCC(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,