RFR: 8264322: Generate CDS archive when creating custom JDK image
Mandy Chung
mchung at openjdk.java.net
Thu Aug 19 00:37:25 UTC 2021
On Wed, 18 Aug 2021 21:21:06 GMT, Calvin Cheung <ccheung at openjdk.org> wrote:
> Please review this change for adding a `jlink` command line option `--generate-cds-archive` for generating CDS archives as a post processing step during the creation of a custom JDK image.
>
> Details can be found in the corresponding CSR [JDK-8269178](https://bugs.openjdk.java.net/browse/JDK-8269178).
>
> Testing:
>
> - [x] tiers 1,2 (including the new test)
src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java line 89:
> 87: private final List<String> args;
> 88: private final Set<String> modules;
> 89: private Platform platform;
Can `DefaultExecutableImage` constructor take an additional `platform` argument and make this `platform` field final?
When the `DefaultExecutableImage` is constructed, it already has the target platform information.
In the constructor, it can check if the `platform` parameter must not be `UNKNOWN`; otherwise throw IAE.
src/jdk.jlink/share/classes/jdk/tools/jlink/builder/DefaultImageBuilder.java line 134:
> 132:
> 133: @Override
> 134: public void setTargetPlatform(Platform p) {
This setter is not needed if it's passed to the constructor.
src/jdk.jlink/share/classes/jdk/tools/jlink/builder/ImageBuilder.java line 82:
> 80: * Gets the target image platform.
> 81: *
> 82: * @return Platform
Suggestion:
* @return {@code Platform} object representing the platform of the runtime image
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ExecutableImage.java line 70:
> 68: * @param p
> 69: */
> 70: public void setTargetPlatform(Platform p);
This method should not be needed. The platform should be known when an executable image is created.
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ExecutableImage.java line 75:
> 73: * The Platform of the image.
> 74: *
> 75: * @return Platform
Suggestion:
* @return {@code Platform} object representing the platform of the runtime image
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ExecutableImage.java line 82:
> 80: * Checks if the image is 64-bit.
> 81: *
> 82: * @return boolean
Suggestion:
* @return true if it's a 64-bit platform
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ExecutableImage.java line 84:
> 82: * @return boolean
> 83: */
> 84: public boolean is64Bit();
This `is64Bit` method should belong to `Platform` class
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java line 195:
> 193: public void operate(ImageProvider provider) throws Exception {
> 194: ExecutableImage img = provider.retrieve(this);
> 195: img.setTargetPlatform(imageBuilder.getTargetPlatform());
See above comment - the ExecutableImage should know the platform when it's constructed.
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Platform.java line 55:
> 53: * Returns the {@code Platform} based on the platformString of the form <operating system>-<arch>.
> 54: */
> 55: public static Platform parseTargetPlatform(String platformString) {
This method can be renamed back to `parsePlatform` (an earlier version). My suggestion to name this method as `parseTargetPlatform` no longer apply in this version.
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java line 80:
> 78: status = p.waitFor();
> 79: } catch (Exception ex) {
> 80: ex.printStackTrace();
This plugin should fail with any exception. jlink will handle `PluginException` and `UncheckedIOException` and print the error message. You can simply wrap IOException with `UncheckedIOException`
try {
Process p = builder.inheritIO().start();
status = p.waitFor();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java line 83:
> 81: }
> 82: if (status == 0) {
> 83: System.out.println("Created " + archiveMsg + " archive successfully");
Is it significant to print two lines on 64-bit platform? Users may not have any idea what `NOCOOPS` means?
Created CDS archive successfully
Created NOCOOPS CDS archive successfully
It seems adequate to me as a user to get one output:
Created CDS archive successfully
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/CDSPlugin.java line 121:
> 119: @Override
> 120: public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
> 121: in.transformAndCopy((file) -> {
This method should not be called in a post-processor. Plugin API needs some re-thinking to support post-processor plugin. As `Plugin::transform` is abstract method, for now this method should simply throw `UnsupportedOperationException`.
src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties line 90:
> 88: \ the runtime image.
> 89:
> 90: main.opt.generate-cds-archive=\
This should not be needed. Leftover from an early version.
src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties line 143:
> 141:
> 142: generate-cds-archive.description=\
> 143: CDS plugin: generate cds archives (classes.jsa, classes_nocoops.jsa).\n\
Is it necessary to show `classes.jsa, classes_nocoops.jsa` the archive file name? Simply drop them?
src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties line 148:
> 146: generate-cds-archive.usage=\
> 147: \ --generate-cds-archive Generate CDS archives (classes.jsa, classes_nocoops.jsa).\n\
> 148: \ Applicable to JDK images built with the CDS feature.
Suggestion:
\ --generate-cds-archive Generate CDS archives if the runtime image supports CDS feature.\n\
Does this match what you want to say?
test/jdk/tools/jlink/plugins/CDSPluginTest.java line 66:
> 64: String sep = File.separator;
> 65: String osName = System.getProperty("os.name");
> 66: if (System.getProperty("os.name").startsWith("Windows")) {
Since this test already depends on `jdk.tools.jlink.internal`, maybe it can use `Platform::runtime` to get the runtime platform.
test/jdk/tools/jlink/plugins/CDSPluginTest.java line 80:
> 78: String jlinkPath = JDKToolFinder.getJDKTool("jlink");
> 79: String[] cmd = {jlinkPath, "--add-modules", "java.base,java.logging",
> 80: "-J-Dos.name=windows", "--generate-cds-archive",
Is there a better way of setting `os.name` system property on the command line?
Maybe override `ModuleTarget` attribute in module-info.class of java.base to be a different platform?
-------------
PR: https://git.openjdk.java.net/jdk/pull/5174
More information about the core-libs-dev
mailing list