diff --git a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java index 69f96955eeabf..50e65b3265632 100644 --- a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java +++ b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java @@ -29,6 +29,7 @@ import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; import sun.invoke.util.Wrapper; +import sun.util.logging.PlatformLogger; import java.util.ArrayList; import java.util.HashSet; @@ -137,10 +138,7 @@ Map build() { for (String invokerType : invokerTypes) { MethodType mt = asMethodType(invokerType); final int lastParam = mt.parameterCount() - 1; - if ((mt.parameterCount() < 2 || - mt.parameterType(0) != Object.class || - mt.parameterType(lastParam) != Object.class) && - !CDS.isDumpingArchive()) { + if (!checkInvokerTypeParams(mt)) { throw new RuntimeException( "Invoker type parameter must start and end with Object: " + invokerType); } @@ -192,7 +190,7 @@ Map build() { return result; } - private static MethodType asMethodType(String basicSignatureString) { + public static MethodType asMethodType(String basicSignatureString) { String[] parts = basicSignatureString.split("_"); assert (parts.length == 2); assert (parts[1].length() == 1); @@ -209,6 +207,13 @@ private static MethodType asMethodType(String basicSignatureString) { } } + public static boolean checkInvokerTypeParams(MethodType mt) { + final int lastParam = mt.parameterCount() - 1; + return (mt.parameterCount() >= 2 && + mt.parameterType(0) == Object.class && + mt.parameterType(lastParam) == Object.class); + } + private void addDMHMethodType(String dmh, String methodType) { validateMethodType(methodType); Set methodTypes = dmhMethods.get(dmh); @@ -317,7 +322,15 @@ static Map generateHolderClasses(Stream traces) { "linkToCallSite".equals(parts[2])) { builder.addCallSiteType(methodType); } else { - builder.addInvokerType(methodType); + MethodType mt = HolderClassBuilder.asMethodType(methodType); + if (HolderClassBuilder.checkInvokerTypeParams(mt)) { + builder.addInvokerType(methodType); + } else { + if (CDS.isDumpingArchive()) { + PlatformLogger.getLogger("java.lang.invoke") + .warning("Invalid LF_RESOLVE " + parts[1] + " " + parts[2] + " " + parts[3]); + } + } } } else if (parts[1].contains("DirectMethodHandle")) { String dmh = parts[2]; diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java index 0191306881b05..61ff5e214a730 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -135,7 +135,7 @@ static void traceLambdaForm(String name, MethodType type, Class holder, Membe (resolvedMember != null ? " (success)" : " (fail)")); } if (CDS.isDumpingClassList()) { - CDS.traceLambdaFormInvoker("[LF_RESOLVE]", holder.getName(), name, shortenSignature(basicTypeSignature(type))); + CDS.traceLambdaFormInvoker("[LF_RESOLVE]", holder.getName(), name, shortenSignature(basicTypeSignature(type)), type); } } diff --git a/src/java.base/share/classes/jdk/internal/misc/CDS.java b/src/java.base/share/classes/jdk/internal/misc/CDS.java index e336544154845..7a2b5687f5349 100644 --- a/src/java.base/share/classes/jdk/internal/misc/CDS.java +++ b/src/java.base/share/classes/jdk/internal/misc/CDS.java @@ -39,6 +39,7 @@ import java.util.stream.Stream; import jdk.internal.access.SharedSecrets; +import java.lang.invoke.MethodType; public class CDS { private static final boolean isDumpingClassList; @@ -109,11 +110,21 @@ public static boolean isDumpingStaticArchive() { */ public static native long getRandomSeedForDumping(); + /** + * Checks if the lambda form invoker is archivable. This is to avoid RuntimeException + * during CDS archive dumping. + */ + private static boolean isInvokerArchivable(MethodType mt, String holder) { + final int lastParam = mt.parameterCount() - 1; + return ((mt.parameterCount() >= 2 && mt.parameterType(0) == Object.class + && mt.parameterType(lastParam) == Object.class) || isValidHolderName(holder)); + } + /** * log lambda form invoker holder, name and method type */ - public static void traceLambdaFormInvoker(String prefix, String holder, String name, String type) { - if (isDumpingClassList) { + public static void traceLambdaFormInvoker(String prefix, String holder, String name, String type, MethodType mt) { + if (isDumpingClassList && isInvokerArchivable(mt, holder)) { logLambdaFormInvoker(prefix + " " + holder + " " + name + " " + type); } }