Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
Hide categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Working with Node.js
      • Node.js Behavior in Heroku
      • Troubleshooting Node.js Apps
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Model Context Protocol
    • Vector Database
    • Heroku Inference
      • Inference Essentials
      • AI Models
      • Inference API
      • Quick Start Guides
    • Working with AI
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Language Support
  • Java
  • Working with Java
  • Customizing the JDK

Customizing the JDK

English — 日本語に切り替える

Last updated April 17, 2025

Table of Contents

  • Prerequisites
  • Specify a JDK version
  • Create a .jdk-overlay folder
  • Add custom files
  • Adding custom certificates
  • Verify the copy
  • Other examples

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

  • A Java app running on Heroku.

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 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 main

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 $JAVA_HOME.

For example, to verify custom certificates were copied correctly, check the $JAVA_HOME/lib/security/ directory.

$ heroku run bash
Running `bash` attached to terminal... up, run.1
~ $ keytool -list -keystore $JAVA_HOME/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.

Keep reading

  • Working with Java

Feedback

Log in to submit feedback.

Warming Up a Java Process Deploying JAR and WAR Files

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices