MacOS system JRE in JavaVirtualMachines with jpackage


I was informed that jpackage had an option to create a DMG that allowed dragging a JRE to JavaVirtualMachines. The location for system JRE's on MacOS. Java command line automatically finds the most current JRE in this directory. jpackage uses the most current to embed as an application's runtime. That is /Library/Java/JavaVirtualMachines. The jpackage option to package a runtime is --runtime-image.

It can be useful to be aware of /usr/libexec/java_home.

/usr/libexec/java_home shows the current default jre home.

/usr/libexec/java_home -v 21 --exec java --version can target a command to a different jre in the JavaVirtualMachines directory.

One use for this could be to test with JRE's that you build. I decided to look at turning a current jdk build into a system jre and also use it embedded in a jpackage built application.

I had the github jdk from prior use. Instructions to build are at Building the JDK My current installed system JRE was jdk-22.0.1.jdk. In order to build current it was indicated that I needed a bootstrap JRE at 23, 24 or 25. I downloaded and installed jdk-23.jdk. I built with...

make images CONF=macosx-aarch64-server-release

I ran jpackage...

jpackage --verbose -n rt -t dmg --runtime-image /Users/mjh/Documents/GitHub/jdk/build/macosx-aarch64-server-release/jdk

This created the rt-1.0.dmg where the rt folder could be dragged and dropped onto JavaVirtualMachines, with authorization. I renamed that to jdk-25.jdk, again with authorization. The directory structure is correct but...

java -version
java version "23.0.1" 2024-10-15
Java(TM) SE Runtime Environment (build 23.0.1+11-39)
Java HotSpot(TM) 64-Bit Server VM (build 23.0.1+11-39, mixed mode, sharing)

As-is it is not recognized as the default runtime. It lacks the necessary MacOS specific files needed for this purpose. I copied these in from the jdk-23.jdk.

Except for the code signature file. It seemed possible some difference between the JRE's could cause an error if that was included. I don't think this is an issue for testing, but it might be for distribution. This isn't intended to be used for distribution. The jdk build instructions above have a section on MacOS signing if it is needed.

Also, the Info.plist needed updating to the correct version.

        ...
   CFBundleGetInfoString
   Java SE 25
        ...
   CFBundleName
   Java SE 25
        ...
   CFBundleShortVersionString
   25
     ...

   JVMPlatformVersion
    25
     ...

   JVMVersion
   25

Then...
java -version
openjdk version "25-internal" 2025-09-16
OpenJDK Runtime Environment (build 25-internal-adhoc.mjh.jdk)
OpenJDK 64-Bit Server VM (build 25-internal-adhoc.mjh.jdk, mixed mode)

Next would be verifying it works with an application. I tried the jpackage build for HalfPipe my java shell application.

[14:31:44.397] Output:
        Error: This JDK does not support linking from the current run-time image

[14:31:44.397] Returned: 2

For some reason the built runtime jpackage doesn't work to build the application. This might be because it's incomplete and not general availability yet. Maybe it should work and this is an issue. I don't know, but it can be worked around. First I changed the build to use the java 23 jpackage.

PACKAGER=`/usr/libexec/java_home -v 23`/bin/jpackage

Then, I pointed the runtime for jpackage to use for the application to the built jdk 25.

--runtime-image /Volumes/rt/rt \

I used the runtime from the DMG. I had tried to piece together a runtime off of the built jdk just by copying it to JavaVirtualMachines and adding the necessary files. This included MacOS alias's that were not then found giving errors. For this walkthrough I did the dmg drag & drop and there didn't appear to be any alias's. It seems that jpackage resolves and eliminates them. So the JavaVirtualMachines jdk25 could probably also have been used but I didn't. This worked as well. The dmg when opened can be used with the /Volumes path on MacOS.

So, a built jdk can be used command line but not as a JavaVirtualMachines system jre and it can't be embedded in applications. Using jpackage and making the manual changes indicated here it can be.

JDK 25 seems to work fine so far.

Testing JavaFX applications might take a little more effort. Using your own built JDK for the application means the jlink parameter --add-modules can't be used as a jpackage parameter, but has to be included as a java parameter via the jpackage -java-options. It also appeared to mean the module path should be the sdk lib directory and and not the jmod's.

This allowed some javafx.swing charting that my application does to work. Although, the application no longer double click launches. It has to be command line started by the native executable. Like MyApp.app/Contents/MacOS/MyApp. I've run into this before but don't remember if I figured anything out on it. For testing purposes it might be adequate.