Skip to content

Conversation

@david-beaumont
Copy link
Contributor

@david-beaumont david-beaumont commented Nov 4, 2025

Creates a new, narrowed API explicitly for use by jlink, which view the resource entries in a jimage file without the re-mapping of names and invention of synthetic entries inherent in ImageReader.

Another good reason to express this new API as something other than ImageReader is that, to fix issues such as JDK-8357249, we don't want to have the (System)ImageReader class used directly in jlink code. It's just the wrong abstraction and will make it harder to refactor jlink to use a non-singleton API with a controlled lifetime later.

I've not added unit tests for the new API (yet), but the fact the PackagedModulesVsRuntimeImageLinkTest passes with preview content in the jimage file means that it's working as expected.


Progress

  • Change must not contain extraneous whitespace

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/valhalla.git pull/1721/head:pull/1721
$ git checkout pull/1721

Update a local copy of the PR:
$ git checkout pull/1721
$ git pull https://git.openjdk.org/valhalla.git pull/1721/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 1721

View PR using the GUI difftool:
$ git pr show -t 1721

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/valhalla/pull/1721.diff

Using Webrev

Link to Webrev Comment

* fixing tests after refactoring
* Fixing up after dependent PR changes
* feedback and remove unused code
* new tests for ImageLocation
* Restoring lost changes and updating some comments.
* add system property guard to preview mode
* Remove TODOs now jimage version is bumped
* jimage writer changes to support preview mode.
@bridgekeeper
Copy link

bridgekeeper bot commented Nov 4, 2025

👋 Welcome back david-beaumont! A progress list of the required criteria for merging this PR into pr/1718 will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Nov 4, 2025

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk openjdk bot added the rfr Pull request is ready for review label Nov 4, 2025
@mlbridge
Copy link

mlbridge bot commented Nov 4, 2025

* obtained is closed.
*/
// Package visible for use by ImageReader.
ResourceEntries getResourceEntries() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the implementation of the new, narrow, API. That's it.

* <p>This API remains valid until the image reader from which it was
* obtained is closed.
*/
public ResourceEntries getResourceEntries() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just exposing the [Shared]ImageReader API out via [System]ImageReader.

I'll probably move this to be package protected here and only publicly available via a static method in SystemImage, which really tightens its use to the one use case we have for it right now.

* <p>It disallows access to resource directories (i.e. {@code "/modules/..."}
* or packages (i.e. {@code "/packages/..."}.
*/
public interface ResourceEntries {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an API so that we can avoid using ImageReader directly in the jlink code.
ImageReader is not conceptually the right API for this, and in future we might want to decouple things even more so it's clear that ImageReader is for inspection of resource in a runtime, and something else is there to read the jimage contents directly.


return new Entry(
archive,
String.format("/%s/%s", archive.moduleName(), resPath),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with the Entry parent class is that it demands a "path", even for cases where none make sense (or at least where the path and name are really the same). This munging of the path to have the module name at the front is what the old code did too, but it really serves no purpose since the path isn't used for this entry.

@Override
public long size() {
try {
if (resType != EntryType.CLASS_OR_RESOURCE) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The checks are asserts are needlessly duplicated in both size() and stream() methods.


//Ask the stack to proceed;
stack.operate(imageProvider);
try (ImageHelper imageProvider =
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ImageHelper holds Archive instances, which should be closed, so putting this in a try-with-resources seems better than what was there.

@Override
public void close() throws IOException {
for (Archive archive : archives) {
archive.close();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could put each close in a try/catch if we were worried about close() actually failing here.

}
}

// Helper to assert the content of two jimage files are the same and provide
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an optional (but nice) improvement to how the test reported mismatched lists of entries.
Without it, the test just fails with no useful output.
If anyone knows a neater way (e.g. some set difference methods) then I'll happily neaten this up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tidied it up (should have done this from the start).

* Constructs an entry of the given archive.
*
* @param archive the archive in which this entry exists.
* @param path the complete path of the entry, including the module.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that now I removed the path() method I added, the path passed here serves absolutely no purpose other than to appear in the toString() output. I'd vote for removing it completely and simplifying callers.

@@ -0,0 +1,71 @@
/*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a copy of the notice in BasicImageReader, so I assume the clause about the GPL is correct.
Please let me know if not.

Comment on lines 34 to 35
* jimage files directly. For inspection of runtime resources, it is vital that
* {@code previewMode} is correctly observed, making this API unsuitable.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be more clearly stated as use API xxx to access the classes and resources of a runtime.

* random order. Entry names will always be prefixed by the given module
* name (e.g. {@code "/<module-name>/..."}).
*/
Stream<String> entryNamesIn(String module);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these names useful with any ImageReader api other than sizeOf or open?

* random order. Entry names will always be prefixed by the given module
* name (e.g. {@code "/<module-name>/..."}).
*/
Stream<String> entryNamesIn(String module);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those extra words at the end of the method name are not consistent with naming conventions in openjdk.
Drop the "In".

Comment on lines 362 to 365
// Other types of invalid name just result in no entry being found.
if (name.startsWith("/modules/") || name.startsWith("/packages/")) {
throw new IllegalArgumentException("Invalid entry name: " + name);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already covered by the == null case below. The distinguished exception isn't necessary.

* @build tests.* jdk.test.lib.process.OutputAnalyzer
* jdk.test.lib.process.ProcessTools
* @run main/othervm/timeout=1200 -Xmx1g PackagedModulesVsRuntimeImageLinkTest
* @run main/othervm/timeout=1200 -ea -esa -DDISABLE_PREVIEW_PATCHING=false -Xmx1g PackagedModulesVsRuntimeImageLinkTest
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this test (temporarily) be run both with and without the new packaging?

@openjdk-notifier openjdk-notifier bot changed the base branch from pr/1718 to lworld November 11, 2025 13:21
@openjdk-notifier
Copy link

The parent pull request that this pull request depends on has now been integrated and the target branch of this pull request has been updated. This means that changes from the dependent pull request can start to show up as belonging to this pull request, which may be confusing for reviewers. To remedy this situation, simply merge the latest changes from the new target branch into this pull request by running commands similar to these in the local repository for your personal fork:

git checkout jdk_8371292_jlink
git fetch https://git.openjdk.org/valhalla.git lworld
git merge FETCH_HEAD
# if there are conflicts, follow the instructions given by git merge
git commit -m "Merge lworld"
git push

@openjdk
Copy link

openjdk bot commented Nov 11, 2025

@david-beaumont this pull request can not be integrated into lworld due to one or more merge conflicts. To resolve these merge conflicts and update this pull request you can run the following commands in the local repository for your personal fork:

git checkout jdk_8371292_jlink
git fetch https://git.openjdk.org/valhalla.git lworld
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge lworld"
git push

@openjdk
Copy link

openjdk bot commented Nov 11, 2025

⚠️ @david-beaumont This pull request contains merges that bring in commits not present in the target repository. Since this is not a "merge style" pull request, these changes will be squashed when this pull request in integrated. If this is your intention, then please ignore this message. If you want to preserve the commit structure, you must change the title of this pull request to Merge <project>:<branch> where <project> is the name of another project in the OpenJDK organization (for example Merge jdk:master).

@openjdk openjdk bot added the merge-conflict Pull request has merge conflict with target branch label Nov 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-conflict Pull request has merge conflict with target branch rfr Pull request is ready for review

Development

Successfully merging this pull request may close these issues.

2 participants