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..cc8aa700750 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,27 @@ 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 uniqueID = targetClass.getName() + + invokedType.toString() + + samMethodName + + samMethodType.toString() + + instantiatedMethodType.toString() + + implMethodClassName + + implMethodName + + implMethodDesc; + uniqueID = uniqueID.replace("$", "_") + .replace(".", "_") + .replace(";", "_") + .replace(",", "_") + .replace("-", "_") + .replace("/", "_") + .replace("[", "_") + .replace("]", "_") + .replace("(", "__") + .replace(")", "__") + .replace("<", "__") + .replace(">", "__"); + lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + uniqueID; cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); int parameterCount = invokedType.parameterCount(); if (parameterCount > 0) { @@ -252,6 +278,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..79f6327a7bc 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,26 @@ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize, if (DUMP_CLASS_FILES) { className = makeDumpableClassName(className); } - this.className = className; + String uniqueID = className + invokerName + invokerType.toString() + lambdaForm.toString(); + uniqueID = uniqueID.replace(",", "_") + .replace("-", "_") + .replace("/", "_") + .replace("\t", "_") + .replace("\n", "_") + .replace(" ", "_") + .replace(":", "_") + .replace(".", "_") + .replace("=", "_") + .replace("<", "_") + .replace(">", "_") + .replace(";", "_") + .replace("{", "_") + .replace("}", "_") + .replace("[", "_") + .replace("]", "_") + .replace("(", "__") + .replace(")", "__"); + this.className = className + "$" + uniqueID; this.lambdaForm = lambdaForm; this.invokerName = invokerName; this.invokerType = invokerType; @@ -690,6 +716,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 +1796,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 +1859,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,