8230301: Re-examine hardcoded defaults in GenerateJLIClassesPlugin
Reviewed-by: mchung
This commit is contained in:
parent
6aeb78d3df
commit
0b5d48b9e6
@ -75,6 +75,7 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXE_SUFFIX) $(CLASSLIST_JAR)
|
||||
$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.raw \
|
||||
-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) \
|
||||
|
@ -31,6 +31,9 @@
|
||||
*/
|
||||
package build.tools.classlist;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.time.LocalDateTime;
|
||||
@ -55,19 +58,20 @@ public class HelloClasslist {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger("Hello");
|
||||
|
||||
public static void main(String ... args) {
|
||||
public static void main(String ... args) throws Throwable {
|
||||
|
||||
FileSystems.getDefault();
|
||||
|
||||
List<String> strings = Arrays.asList("Hello", "World!", "From: ",
|
||||
InetAddress.getLoopbackAddress().toString());
|
||||
InetAddress.getLoopbackAddress().toString());
|
||||
|
||||
String helloWorld = strings.parallelStream()
|
||||
.map(s -> s.toLowerCase(Locale.ROOT))
|
||||
.collect(joining(","));
|
||||
.map(s -> s.toLowerCase(Locale.ROOT))
|
||||
.collect(joining(","));
|
||||
|
||||
Stream.of(helloWorld.split(","))
|
||||
.forEach(System.out::println);
|
||||
Stream.of(helloWorld.split("([,x-z]{1,3})([\\s]*)"))
|
||||
.map(String::toString)
|
||||
.forEach(System.out::println);
|
||||
|
||||
// Common concatenation patterns
|
||||
String SS = String.valueOf(args.length) + String.valueOf(args.length);
|
||||
@ -83,6 +87,10 @@ public class HelloClasslist {
|
||||
String SCSCS = String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length);
|
||||
String CI = "string" + args.length;
|
||||
String IC = args.length + "string";
|
||||
String SI = String.valueOf(args.length) + args.length;
|
||||
String IS = args.length + String.valueOf(args.length);
|
||||
String CIS = "string" + args.length + String.valueOf(args.length);
|
||||
String CSCI = "string" + String.valueOf(args.length) + "string" + args.length;
|
||||
String CIC = "string" + args.length + "string";
|
||||
String CICI = "string" + args.length + "string" + args.length;
|
||||
String CJ = "string" + System.currentTimeMillis();
|
||||
@ -99,7 +107,31 @@ public class HelloClasslist {
|
||||
DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.ROOT)
|
||||
.format(new Date()));
|
||||
|
||||
// A selection of trivial and relatively common MH operations
|
||||
invoke(MethodHandles.identity(double.class), 1.0);
|
||||
invoke(MethodHandles.identity(int.class), 1);
|
||||
invoke(MethodHandles.identity(String.class), "x");
|
||||
|
||||
invoke(handle("staticMethod_V", MethodType.methodType(void.class)));
|
||||
|
||||
LOGGER.log(Level.FINE, "New Date: " + newDate + " - old: " + oldDate);
|
||||
}
|
||||
|
||||
public static void staticMethod_V() {}
|
||||
|
||||
private static MethodHandle handle(String name, MethodType type) throws Throwable {
|
||||
return MethodHandles.lookup().findStatic(HelloClasslist.class, name, type);
|
||||
}
|
||||
|
||||
private static Object invoke(MethodHandle mh, Object ... args) throws Throwable {
|
||||
try {
|
||||
for (Object o : args) {
|
||||
mh = MethodHandles.insertArguments(mh, 0, o);
|
||||
}
|
||||
return mh.invoke();
|
||||
} catch (Throwable t) {
|
||||
LOGGER.warning("Failed to find, link and/or invoke " + mh.toString() + ": " + t.getMessage());
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,21 @@ import jdk.tools.jlink.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Plugin to generate java.lang.invoke classes.
|
||||
*
|
||||
* The plugin reads in a file generated by running any application with
|
||||
* {@code -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true}. This is done
|
||||
* automatically during build, see make/GenerateLinkOptData.gmk. See
|
||||
* build/tools/classlist/HelloClasslist.java for the training application.
|
||||
*
|
||||
* HelloClasslist tries to reflect common use of java.lang.invoke during early
|
||||
* startup and warmup in various applications. To ensure a good default
|
||||
* trade-off between static footprint and startup the application should be
|
||||
* relatively conservative.
|
||||
*
|
||||
* When using jlink to build a custom application runtime, generating a trace
|
||||
* file using {@code -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true} and
|
||||
* feeding that into jlink using {@code --generate-jli-classes=@trace_file} can
|
||||
* help improve startup time.
|
||||
*/
|
||||
public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
|
||||
@ -112,59 +127,6 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
return PluginsResourceBundle.getArgument(NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default Species forms to generate.
|
||||
*
|
||||
* This list was derived from running a small startup benchmark.
|
||||
* A better long-term solution is to define and run a set of quick
|
||||
* generators and extracting this list as a step in the build process.
|
||||
*/
|
||||
public static Set<String> defaultSpecies() {
|
||||
return Set.of("LL", "L3", "L4", "L5", "L6", "L7", "L7I",
|
||||
"L7II", "L7IIL", "L8", "L9", "L10", "L10I", "L10II", "L10IIL",
|
||||
"L11", "L12", "L13", "LI", "D", "L3I", "LIL", "LLI", "LLIL",
|
||||
"LILL", "I", "LLILL");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default invoker forms to generate.
|
||||
*/
|
||||
private static Set<String> defaultInvokers() {
|
||||
return Set.of("LL_L", "LL_I", "LLLL_L", "LLLL_I", "LLIL_L", "LLIL_I",
|
||||
"L6_L");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default call site forms to generate (linkToTargetMethod).
|
||||
*/
|
||||
private static Set<String> defaultCallSiteTypes() {
|
||||
return Set.of("L5_L", "LIL3_L", "ILL_L");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of default DirectMethodHandle methods to generate.
|
||||
*/
|
||||
private static Map<String, Set<String>> defaultDMHMethods() {
|
||||
return Map.of(
|
||||
DMH_INVOKE_INTERFACE, Set.of("LL_L", "L3_I", "L3_V"),
|
||||
DMH_INVOKE_VIRTUAL, Set.of("LL_L", "LLI_I", "L3_V"),
|
||||
DMH_INVOKE_SPECIAL, Set.of("LL_I", "LL_L", "LLF_L", "LLD_L",
|
||||
"L3_I", "L3_L", "L4_L", "L5_L", "L6_L", "L7_L", "L8_L",
|
||||
"LLI_I", "LLI_L", "LLIL_I", "LLIL_L", "LLII_I", "LLII_L",
|
||||
"L3I_L", "L3I_I", "L3ILL_L", "LLILI_I", "LLIIL_L", "LLIILL_L",
|
||||
"LLIILL_I", "LLIIL_I", "LLILIL_I", "LLILILL_I", "LLILII_I",
|
||||
"LLI3_I", "LLI3L_I", "LLI3LL_I", "LLI3_L", "LLI4_I"),
|
||||
DMH_INVOKE_STATIC, Set.of("LII_I", "LIL_I", "LILIL_I", "LILII_I",
|
||||
"L_I", "L_L", "L_V", "LD_L", "LF_L", "LI_I", "LII_L", "LLI_L",
|
||||
"LL_I", "LLILL_L", "LLIL3_L", "LL_V", "LL_L", "L3_I", "L3_L",
|
||||
"L3_V", "L4_I", "L4_L", "L5_L", "L6_L", "L7_L", "L8_L", "L9_L",
|
||||
"L10_L", "L10I_L", "L10II_L", "L10IIL_L", "L11_L", "L12_L",
|
||||
"L13_L", "L14_L", "L14I_L", "L14II_L"),
|
||||
DMH_NEW_INVOKE_SPECIAL, Set.of("L_L", "LL_L"),
|
||||
DMH_INVOKE_SPECIAL_IFC, Set.of("L5_I")
|
||||
);
|
||||
}
|
||||
|
||||
private static int DMH_INVOKE_VIRTUAL_TYPE = 0;
|
||||
private static int DMH_INVOKE_INTERFACE_TYPE = 4;
|
||||
|
||||
@ -201,19 +163,8 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
}
|
||||
|
||||
public void initialize(ResourcePool in) {
|
||||
// Start with the default configuration
|
||||
defaultSpecies().stream().forEach(this::addSpeciesType);
|
||||
|
||||
defaultInvokers().stream().forEach(this::validateMethodType);
|
||||
|
||||
defaultCallSiteTypes().stream().forEach(this::addCallSiteType);
|
||||
|
||||
defaultDMHMethods().entrySet().stream().forEach(e -> {
|
||||
e.getValue().stream().forEach(type -> addDMHMethodType(e.getKey(), type));
|
||||
});
|
||||
|
||||
// Extend the default configuration with the contents in the supplied
|
||||
// input file - if none was supplied we look for the default file
|
||||
// Load configuration from the contents in the supplied input file
|
||||
// - if none was supplied we look for the default file
|
||||
if (mainArgument == null || !mainArgument.startsWith("@")) {
|
||||
try (InputStream traceFile =
|
||||
this.getClass().getResourceAsStream(DEFAULT_TRACE_FILE)) {
|
||||
|
@ -29,8 +29,6 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin;
|
||||
|
||||
import tests.Helper;
|
||||
import tests.JImageGenerator;
|
||||
import tests.JImageValidator;
|
||||
@ -62,32 +60,19 @@ public class GenerateJLIClassesPluginTest {
|
||||
|
||||
helper.generateDefaultModules();
|
||||
|
||||
// Test that generate-jli is enabled by default
|
||||
Result result = JImageGenerator.getJLinkTask()
|
||||
.modulePath(helper.defaultModulePath())
|
||||
.output(helper.createNewImageDir("generate-jli"))
|
||||
.addMods("java.base")
|
||||
.call();
|
||||
|
||||
Path image = result.assertSuccess();
|
||||
|
||||
JImageValidator.validate(image.resolve("lib").resolve("modules"),
|
||||
classFilesForSpecies(GenerateJLIClassesPlugin.defaultSpecies()),
|
||||
List.of());
|
||||
|
||||
// Check that --generate-jli-classes=@file works as intended
|
||||
Path baseFile = Files.createTempFile("base", "trace");
|
||||
String species = "LLLLLLLLLLLLLLLLLLL";
|
||||
String fileString = "[SPECIES_RESOLVE] java.lang.invoke.BoundMethodHandle$Species_" + species + " (salvaged)\n";
|
||||
Files.write(baseFile, fileString.getBytes(Charset.defaultCharset()));
|
||||
result = JImageGenerator.getJLinkTask()
|
||||
Result result = JImageGenerator.getJLinkTask()
|
||||
.modulePath(helper.defaultModulePath())
|
||||
.output(helper.createNewImageDir("generate-jli-file"))
|
||||
.option("--generate-jli-classes=@" + baseFile.toString())
|
||||
.addMods("java.base")
|
||||
.call();
|
||||
|
||||
image = result.assertSuccess();
|
||||
Path image = result.assertSuccess();
|
||||
|
||||
JImageValidator.validate(image.resolve("lib").resolve("modules"),
|
||||
classFilesForSpecies(List.of(species)), // species should be in the image
|
||||
@ -119,8 +104,7 @@ public class GenerateJLIClassesPluginTest {
|
||||
|
||||
private static List<String> classFilesForSpecies(Collection<String> species) {
|
||||
return species.stream()
|
||||
.map(s -> "/java.base/java/lang/invoke/BoundMethodHandle$Species_"
|
||||
+ GenerateJLIClassesPlugin.expandSignature(s) + ".class")
|
||||
.map(s -> "/java.base/java/lang/invoke/BoundMethodHandle$Species_" + s + ".class")
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user