Skip to content

8351073: [macos] jpackage produces invalid Java runtime DMG bundles #25314

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

sashamatveev
Copy link
Member

@sashamatveev sashamatveev commented May 20, 2025

Fixed jpackage to produce valid Java runtimes based on description below:

Definitions:

  • JDK bundle defined as bundle which contains "Contents/Home", "Contents/MacOS/libjli.dylib" and "Contents/Info.plist".
  • Signed JDK bundle contains all files as JDK bundle + "Contents/_CodeSignature".
  • JDK image defined as content of "Contents/Home".
  • Signed JDK image does not exist, since it cannot be signed as bundle.

jpackage output based on input:

  1. "--runtime-image" points to unsigned JDK bundle and --mac-sign is not provided:
  • jpackage will copy all files as is from provided path and run ad-hoc codesign.
  1. "--runtime-image" points to unsigned JDK bundle and --mac-sign is provided:
  • jpackage will copy all files as is from provided path and run codesign with appropriate certificate based on same logic as we do for application image.
  1. "--runtime-image" points to signed JDK bundle and --mac-sign is not provided:
  • jpackage will copy all files as is from provided path including "Contents/_CodeSignature" to preserve signing.
  1. "--runtime-image" points to signed JDK bundle and --mac-sign is provided:
  • jpackage will copy all files as is from provided path including "Contents/_CodeSignature" and will re-sign bundle with appropriate certificate.
  1. "--runtime-image" points to JDK image and --mac-sign is not provided:
  • jpackage will check for libjli.dylib presence in "lib" folder.
  • Create JDK bundle by putting all files from provided path to "Contents/Home", libjli.dylib from "lib" to "Contents/MacOS/libjli.dylib" and create default "Contents/Info.plist" similar to what we do for runtime in application image.
  • Ad-hoc signing will done.
  1. "--runtime-image" points to JDK image and --mac-sign is provided:
  • 2 first steps from 5 and certificate signing will be done.

Additional changes:

  • The bundle's top directory name will have the ".jdk" suffix.

Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Warnings

 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/java/awt/doc-files/BorderLayout-1.gif)
 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/java/awt/doc-files/FlowLayout-1.gif)
 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/java/awt/doc-files/GridBagLayout-1.gif)
 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/java/awt/doc-files/GridBagLayout-2.gif)
 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/java/awt/doc-files/GridLayout-1.gif)
 ⚠️ Patch contains a binary file (src/java.desktop/share/classes/java/awt/doc-files/GridLayout-2.gif)

Issue

  • JDK-8351073: [macos] jpackage produces invalid Java runtime DMG bundles (Bug - P4)(⚠️ The fixVersion in this issue is [26] but the fixVersion in .jcheck/conf is 25, a new backport will be created when this pr is integrated.)

Reviewing

Using git

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

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

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 25314

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

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/25314.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented May 20, 2025

👋 Welcome back almatvee! A progress list of the required criteria for merging this PR into master 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 May 20, 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 May 20, 2025
@openjdk
Copy link

openjdk bot commented May 20, 2025

@sashamatveev The following label will be automatically applied to this pull request:

  • core-libs

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@mlbridge
Copy link

mlbridge bot commented May 20, 2025

Webrevs

@mlbridge
Copy link

mlbridge bot commented May 20, 2025

Mailing list message from Michael Hall on core-libs-dev:

On May 19, 2025, at 7:53?PM, Alexander Matveev <almatvee at openjdk.org> wrote:

Fixed jpackage to produce valid Java runtimes based on description below:

Definitions:

Thanks for the follow-up.

To the comments on the issue of would it be useful for jpackage to do this.

The runtime images that you get with make images doesn?t work for applications. So it can?t be used to test applications. I assume your changes make that possible. How often you might want to test
jdk builds against applications I don?t know.

Validation again seemed to me to be important. In trying this out I attempted different ways to use the ?runtime-image parameter. All of them succeeded in creating dmg?s but the images were not valid.

Is there some test being added?

@mlbridge
Copy link

mlbridge bot commented May 20, 2025

Mailing list message from Michael Hall on core-libs-dev:

On May 20, 2025, at 4:13?AM, Michael Hall <mik3hall at gmail.com> wrote:

The runtime images that you get with make images doesn?t work for applications.

I might be misremembering on this. It might be useable as a runtime image to embed in applications with jpackage?
It is not valid as a system runtime image that can be installed into JavaVirtualMachines and become the default system runtime for command line and applications.
This would sort of seem the purpose of a jpackage option that allows putting a runtime into a dmg that can be drag and drop installed into JavaVirtualMachines.
It should be a valid runtime for this purpose.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20250520/6f939fb1/attachment.htm>

Comment on lines 188 to 199
VERSION::fetchFrom,
params -> {
String version = VERSION.fetchFrom(params);
// Special case for MSI product version for runtime
// installer. Runtime version can be single digit
// for example "25", but product version requires 2 or 4
// components. JDK uses "25.0.0.0" in this case.
if (StandardBundlerParam.isRuntimeInstaller(params) &&
!version.contains(".")) {
version = version.concat(".0.0.0");
}
return version;
},

Choose a reason for hiding this comment

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

I guess, this is a workaround for the case when the version comes from JDK's release file. This is the wrong place for this workaround. It should be a part of the code reading version from JDK's release file.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this is workaround when the version comes from JDK's release file. In this case name will be customeJDK-25.0.0.0 for example if we change it when we read version form file. Other platform do not need it. Only PRODUCT_VERSION in MSI needs to be 2 or 4 components, so I think it is correct location for it.

Choose a reason for hiding this comment

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

For runtime packaging, the version can be taken from the command line or the "release" file. In the latter case the version should be valid for the current platform and packaging type. Version adjustments should be isolated in a function that reads a version from the "release" file. The result of this function call should be such that it will be used as-is without any modifications.

Ideally, we should have Optional<String> readVersionFromRuntimeReleaseFile(String packageType, Path pathToReleaseFile) function that we can unit test and that will return a valid version for the given packaging type ("packageType" parameter). It should return an empty Optional instance if it fails.

RUNTIME_IMAGE(new Builder("--runtime-image").enable(cmd -> {
// External runtime image should be R/O unless it is on macOS.
// On macOS it will be signed ad-hoc or with real certificate.
return !TKit.isOSX();
Copy link
Member

@alexeysemenyukoracle alexeysemenyukoracle May 20, 2025

Choose a reason for hiding this comment

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

Do I get the comment right, and jpackage will modify the image supplied with --runtime-image parameter? This is wrong. jpackage must not modify any externally supplied files/directories unless this is app image signing on macos.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, you get the comment right. We do sign runtime image as well (same as app image). We do ad-hoc signing for runtime image if signing is not requested. Ad-hoc signing will modify runtime image. I think you mean case when "--app-image" and "--runtime-image" is specified, then yes we should not modify it, but when we packaging just runtime it will be modify due to signature. I will update test to reflect it.

@@ -334,7 +334,7 @@ static Path getInstallationDirectory(JPackageCommand cmd) {
installLocation = cmd.getArgumentValue("--install-dir", () -> defaultInstallLocation, Path::of);
}

return installLocation.resolve(cmd.name() + (cmd.isRuntime() ? "" : ".app"));
return installLocation.resolve(cmd.name() + (cmd.isRuntime() ? ".jdk" : ".app"));

Choose a reason for hiding this comment

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

Why the ".jdk" suffix and not ".app"?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because JDK bundles has ".jdk" suffix. Why it should be ".app"?

@alexeysemenyukoracle
Copy link
Member

The description is missing some important changes:

  • jpackage will attempt to get a package version from the JDK's release file if the --version option is not specified.
  • The bundle's top directory name will have the ".jdk" suffix.

I like the idea of reading the package's version from the JDK's release file when bundling a runtime package, but it is out of the scope of the "jpackage produces invalid Java runtime DMG bundles" fix. It should be a separate fix.

@sashamatveev
Copy link
Member Author

I updated description.

@sashamatveev
Copy link
Member Author

8351073: [macos] jpackage produces invalid Java runtime DMG bundles [v2]

  • Addresses the above comments.

Comment on lines +101 to +102
TKit.error(ex.getMessage());
return null;

Choose a reason for hiding this comment

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

What is the point of this exception "handling"? What problem does it solve? What is the caller supposed to do with the null?

@@ -88,6 +90,31 @@ enum Token {

return appImageCmd.outputBundle().toString();
}),
INVALID_JDK_BUNDLE(cmd -> {

Choose a reason for hiding this comment

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

Would INVALID_MAC_JDK_BUNDLE name be more accurate?

@sashamatveev
Copy link
Member Author

8351073: [macos] jpackage produces invalid Java runtime DMG bundles [v3]

  • Removed "jpackage will attempt to get a package version from the JDK's release file if the --version option is not specified". It will be fixed as separate issue under: JDK-8357404.

@openjdk
Copy link

openjdk bot commented May 28, 2025

@sashamatveev this pull request can not be integrated into master 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-8351073
git fetch https://git.openjdk.org/jdk.git master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push

@openjdk openjdk bot added the merge-conflict Pull request has merge conflict with target branch label May 28, 2025
@sashamatveev sashamatveev marked this pull request as draft June 13, 2025 22:30
@openjdk openjdk bot removed the rfr Pull request is ready for review label Jun 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core-libs [email protected] merge-conflict Pull request has merge conflict with target branch
Development

Successfully merging this pull request may close these issues.

2 participants