Goal
...
Improve start-up time by storing pre-generated LambdaForm handlers in an application-specific CDS archive.
Background
...
In JDK-8086045 Improve the java.lang.invoke first initialization costs, the JDK can reduce the number of dynamically generated LambdaForm classes. Here's an example:
...
Code Block |
---|
private static final String DIRECT_HOLDER = "java/lang/invoke/DirectMethodHandle$Holder";
...
byte[] bytes = JLIA.generateDirectMethodHandleHolderClassBytes(
DIRECT_HOLDER, directMethodTypes, dmhTypes); |
The input of generateDirectMethodHandleHolderClassBytes comes from the default_jli_trace.txt file that is generated in GenerateLinkOptData.gmk:
Code Block |
---|
$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.raw.2 \
-XX:SharedClassListFile=$@.interim -XX:SharedArchiveFile=$@.jsa \
-Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \
-Duser.language=en -Duser.country=US \
--module-path $(SUPPORT_OUTPUTDIR)/classlist.jar \
-cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
build.tools.classlist.HelloClasslist \
2> $(LINK_OPT_DIR)/stderr > $(JLI_TRACE_FILE) |
Here's how roughly the contents of default_jli_trace.txt correspond to the generated methods in DirectMethodHandle$Holder
Code Block |
---|
$ grep invokeSpecialIFC ./support/link_opt/default_jli_trace.txt [LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecialIFC L3I_I (fail) [LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeSpecialIFC LLI_I (fail) $ images/jdk/bin/javap 'java.lang.invoke.DirectMethodHandle$Holder' | grep invokeSpecialIFC static int invokeSpecialIFC(java.lang.Object, java.lang.Object, java.lang.Object, int); static int invokeSpecialIFC(java.lang.Object, java.lang.Object, int); |
The methods in DirectMethodHandle$Holder are used in InvokerBytecodeGenerator.java when compiling for LambdaForms:
Code Block |
---|
private static MemberName lookupPregenerated(LambdaForm form, MethodType invokerType) {
if (form.customized != null) {
// No pre-generated version for customized LF
return null;
}
String name = form.kind.methodName;
switch (form.kind) {
[......]
case DIRECT_INVOKE_INTERFACE: // fall-through
case DIRECT_INVOKE_SPECIAL: // fall-through
case DIRECT_INVOKE_SPECIAL_IFC: // fall-through
case DIRECT_INVOKE_STATIC: // fall-through
case DIRECT_INVOKE_STATIC_INIT: // fall-through
case DIRECT_INVOKE_VIRTUAL: return resolveFrom(name, invokerType, DirectMethodHandle.Holder.class);
}
return null; |