RFR: 8311302: Implement JEP 493: Linking Run-Time Images without JMODs [v41]
Mandy Chung
mchung at openjdk.org
Thu Oct 31 18:43:58 UTC 2024
On Wed, 30 Oct 2024 21:12:42 GMT, Severin Gehwolf <sgehwolf at openjdk.org> wrote:
>> Please review this patch which adds a jlink mode to the JDK which doesn't need the packaged modules being present. A.k.a run-time image based jlink. Fundamentally this patch adds an option to use `jlink` even though your JDK install might not come with the packaged modules (directory `jmods`). This is particularly useful to further reduce the size of a jlinked runtime. After the removal of the concept of a JRE, a common distribution mechanism is still the full JDK with all modules and packaged modules. However, packaged modules can incur an additional size tax. For example in a container scenario it could be useful to have a base JDK container including all modules, but without also delivering the packaged modules. This comes at a size advantage of `~25%`. Such a base JDK container could then be used to `jlink` application specific runtimes, further reducing the size of the application runtime image (App + JDK runtime; as a single image *or* separate bundles, depending on the app
being modularized).
>>
>> The basic design of this approach is to add a jlink plugin for tracking non-class and non-resource files of a JDK install. I.e. files which aren't present in the jimage (`lib/modules`). This enables producing a `JRTArchive` class which has all the info of what constitutes the final jlinked runtime.
>>
>> Basic usage example:
>>
>> $ diff -u <(./bin/java --list-modules --limit-modules java.se) <(../linux-x86_64-server-release/images/jdk/bin/java --list-modules --limit-modules java.se)
>> $ diff -u <(./bin/java --list-modules --limit-modules jdk.jlink) <(../linux-x86_64-server-release/images/jdk/bin/java --list-modules --limit-modules jdk.jlink)
>> $ ls ../linux-x86_64-server-release/images/jdk/jmods
>> java.base.jmod java.net.http.jmod java.sql.rowset.jmod jdk.crypto.ec.jmod jdk.internal.opt.jmod jdk.jdi.jmod jdk.management.agent.jmod jdk.security.auth.jmod
>> java.compiler.jmod java.prefs.jmod java.transaction.xa.jmod jdk.dynalink.jmod jdk.internal.vm.ci.jmod jdk.jdwp.agent.jmod jdk.management.jfr.jmod jdk.security.jgss.jmod
>> java.datatransfer.jmod java.rmi.jmod java.xml.crypto.jmod jdk.editpad.jmod jdk.internal.vm.compiler.jmod jdk.jfr.jmod jdk.management.jmod jdk.unsupported.desktop.jmod
>> java.desktop.jmod java.scripting.jmod java.xml.jmod jdk.hotspot.agent.jmod jdk.i...
>
> Severin Gehwolf has updated the pull request incrementally with 20 additional commits since the last revision:
>
> - Some test fixes
> - Remove period in jlink.properties
> - Revert changes to ResourcePoolEntry
> - Fix comment in RuntimeImageLinkException
> - Remove ImageReader (like JmodsReader)
> - More comment fixes (JlinkTask)
> - Move some comments around
> - More comment fix-ups (JRTArchive)
> - Fix description of configure option
> - Some more wording updates
> - ... and 10 more: https://git.openjdk.org/jdk/compare/83a86d06...e6b3aeb1
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java line 151:
> 149: public static void recreateJimage(Path jimageFile,
> 150: Set<Archive> archives,
> 151: ImagePluginStack pluginSupport, boolean generateRuntimeImage)
Suggestion:
ImagePluginStack pluginSupport,
boolean generateRuntimeImage)
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java line 195:
> 193: plugins.storeFiles(allContent.resourcePool(), result, writer);
> 194: } catch (RuntimeImageLinkException e) {
> 195: throwRuntimeLinkFailure(e);
Curious why this is a special case. Would it be useful for debugging if this throws `new IOException(e)` the same way as other exceptions (line 196-200) so RILE is a cause?
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java line 255:
> 253: } catch (RuntimeImageLinkException re) {
> 254: // Might be thrown when linking from the current run-time image.
> 255: // Populate the actual reason.
`// Populate the actual reason.` - this comment no longer applies?
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java line 338:
> 336: @SuppressWarnings("try")
> 337: private static ResourcePool addResourceDiffFiles(ResourcePool jmodContent,
> 338: ResourcePool resultContent, BasicImageWriter writer) {
Suggestion:
ResourcePool resultContent,
BasicImageWriter writer) {
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java line 399:
> 397: String mResource = String.format(DIFF_PATH, module);
> 398: List<ResourceDiff> diff = perModDiffs.get(module);
> 399: if (diff == null) {
Can `diff` ever be null? ` preparePerModuleDiffs` ensures that the return map has one entry for each module and empty list if no diff.
For the case with no diff, do you expect EMPTY_RESOURCE_BYTES or a `ResourceDiff` content with header & zero entry?
Perhaps line 377-386 in `preparePerModuleDiffs` can simply be removed and let `addDiffResourcesFiles` to handle no resource diff case as it does now.
Map<String, List<ResourceDiff>> allModsToDiff = new HashMap<>();
modules.stream().forEach(m -> {
List<ResourceDiff> d = modToDiff.get(m);
if (d == null) {
// Not all modules will have a diff
allModsToDiff.put(m, Collections.emptyList());
} else {
allModsToDiff.put(m, d);
}
});
return allModsToDiff;
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java line 435:
> 433: BasicImageWriter writer) {
> 434: // Only add resources if we have the jdk.jlink module part of the
> 435: // target modules view
Suggestion:
// Only add resources if jdk.jlink module is present in the target image
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java line 543:
> 541:
> 542: private static ResourcePoolManager createBasicResourcePoolManager(
> 543: ByteOrder byteOrder, BasicImageWriter writer) {
Suggestion:
private static ResourcePoolManager createBasicResourcePoolManager(ByteOrder byteOrder,
BasicImageWriter writer) {
src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java line 567:
> 565: */
> 566: private static ResourcePoolManager createPoolManager(
> 567: ResourcePool resultResources, BasicImageWriter writer) {
Suggestion:
private static ResourcePoolManager createPoolManager(ResourcePool resultResources,
BasicImageWriter writer) {
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/14787#discussion_r1823546245
PR Review Comment: https://git.openjdk.org/jdk/pull/14787#discussion_r1823539718
PR Review Comment: https://git.openjdk.org/jdk/pull/14787#discussion_r1823544168
PR Review Comment: https://git.openjdk.org/jdk/pull/14787#discussion_r1823545856
PR Review Comment: https://git.openjdk.org/jdk/pull/14787#discussion_r1823585738
PR Review Comment: https://git.openjdk.org/jdk/pull/14787#discussion_r1823574545
PR Review Comment: https://git.openjdk.org/jdk/pull/14787#discussion_r1823578438
PR Review Comment: https://git.openjdk.org/jdk/pull/14787#discussion_r1823579074
More information about the build-dev
mailing list