Customizing the JDK
Last updated May 03, 2024
Table of Contents
There are some cases where files need to be bundled with the JDK in order to expose functionality in the runtime JVM. For example, the inclusion of a custom certificate authority (CA) store is common. To handle such cases, Heroku will copy files designated by the app in a .jdk-overlay
folder into the JDK’s directory structure.
To include additional files in the JVM, follow these instructions:
Prerequisites
Specify a JDK version
Create a system.properties
file if one does not already exist, specify the version, and commit it to git. Supported version are described in the Java Support article. The file’s contents should look something like this:
java.runtime.version=11
Then add the file to Git by running:
$ git add system.properties
$ git commit -m "JDK 11"
Create a .jdk-overlay
folder
In your application’s root directory, create a .jdk-overlay
folder.
$ mkdir .jdk-overlay
$ ls -la
total 24
drwxr-xr-x 9 user staff 306 Oct 16 14:43 .
drwxr-xr-x 202 user staff 6868 Oct 16 14:40 ..
drwxr-xr-x 13 user staff 442 Oct 16 15:06 .git
drwxr-xr-x 3 user staff 102 Oct 16 14:43 .jdk-overlay
-rw-r--r-- 1 user staff 45 Oct 16 14:40 Procfile
-rw-r--r-- 1 user staff 1860 Oct 16 14:40 pom.xml
drwxr-xr-x 3 user staff 102 Oct 16 14:40 src
-rw-r--r-- 1 user staff 25 Oct 16 14:40 system.properties
Add custom files
Copy any custom files into the .jdk-overlay
directory. The files will be copied to their equivalent directory in the JDK. For example, to define a custom security policy, the java.policy
file could be placed in the .jdk-overlay/jre/lib/security/
(.jdk-overlay/lib/security
for Java 9 and higher) directory of your app’s repository.
Adding custom certificates
You may also need to add custom certificates to the JDK’s cacerts
. You may start with the keystore in your local JDK or download the base Heroku keystore. Add the custom certificate with:
$ keytool -import -keystore cacerts -file custom.cer
You may be prompted for a password. The default password is changeit
. You may then include the keystore in the slug by placing it in the .jdk-overlay/jre/lib/security/
directory of your app’s repository (or .jdk-overlay/lib/security/
for Java 9 and higher).
Now add any custom files to your Git repo like this:
$ git add .jdk-overlay
$ git commit -m "Custom JDK Files"
Then deploy your application, with the custom files, to Heroku:
$ git push heroku master
This overrides the keystore of your JDK. Your application no longer benefits from automatic keystore updates when the Stack is updated.
Verify the copy
The copies can be verified by starting a bash session on Heroku and checking the JDK directory. The JDK directory is located in $HOME/.jdk/
.
For example, to verify custom certificates were copied correctly, the $HOME/.jdk/jre/lib/security/
directory can be checked.
$ heroku run bash
Running `bash` attached to terminal... up, run.1
~ $ keytool -list -keystore .jdk/jre/lib/security/cacerts
...
Your keystore contains 140 entries
...
Other examples
This method can be used for Java extensions when necessary. Though a dependency management tool, such as Maven, should be the preferred mechanism for introducing dependencies.