The JDK caching section quoted informal figures from the feature PR. The setup-java-benchmarks repository now has a JDK cache scenario workflow that reproduces the comparison end to end, so cite its numbers across two independent runs and name the workflow instead. Also record the cold-run cost, the flat build-step control, and the fact that the job-level median is noisier than the setup-step median, so the tradeoff is explicit rather than implying the speedup is free or precise. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 664777db-7250-417d-b94d-d5529ec3fec2
Setup Java
Set up Java for GitHub Actions workflows. setup-java installs a requested Java distribution, adds it to PATH, configures JAVA_HOME, and can optionally cache build dependencies for Apache Maven, Gradle, and sbt; generate Maven publishing configuration, verify JDK package signatures, manage multiple JDKs, and manage Maven toolchains.
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
- run: java --version
Note
V6 is still in development on the
mainbranch and is not yet recommended for production workflows. To use it, you must explicitly reference themainbranch in your workflow, as in- uses: actions/setup-java@mainFor production workflows, it is recommended to use the latest stable release
v5.
Contents
- What it does
- What's new
- Usage
- Inputs
- Supported distributions
- Supported version syntax
- Caching
- Multiple JDKs and Maven toolchains
- Publishing packages
- Advanced usage
What it does
- Downloads and installs Java from a supported distribution.
- Uses a requested Java version, a version file, or the
lateststable release alias. - Extracts and caches a custom JDK archive from a local file.
- Configures Maven
settings.xml, Maven Toolchains, Maven GPG signing inputs, and environment-variable based credentials for publishing workflows. - Registers Java problem matchers for compiler diagnostics and uncaught exceptions.
- Caches dependencies for Maven, Gradle, and sbt.
- Caches downloaded JDK installations between jobs.
- Verifies downloaded archive checksums when a distribution publishes authoritative checksums.
- Optionally verifies package signatures for supported distributions.
setup-java works with Java, Scala, Kotlin, Gradle, Maven, and sbt projects.
What's new
V6 (in development)
- Migrated the action implementation to ESM to support the latest
@actions/*packages. - Added the
oracle-openjdkdistribution for OpenJDK builds from Oracle. - Added
java-version: latestto resolve the newest stable GA release from the distribution's remote metadata. - JDK downloads now automatically verify authoritative checksums for supported distributions.
- Added
force-download: trueto bypass the tool cache and perform a reproducible fresh install. - Dependency caching now supports custom paths with
cache-pathand restore-only operation withcache-read-only: true. - Downloaded JDKs are now cached automatically when
cacheis set; usecache-jdkto enable or disable it independently. - Set
problem-matcher: falseto disable Java compiler and uncaught-exception annotations. - GraalVM distributions now set
GRAALVM_HOMEin addition toJAVA_HOME. - Invalid boolean values, unsupported distribution/package/platform combinations, and mismatched Maven toolchain ID counts now fail with targeted errors.
- Renamed environment-variable-name inputs so they are not mistaken for secret values:
server-username->server-username-env-varserver-password->server-password-env-vargpg-passphrase->gpg-passphrase-env-var
- Deprecated aliases still work, but emit warnings.
- Maven GPG passphrases are now passed through
gpg.passphraseEnvNameinstead of a deprecatedgpg.passphraseserver entry insettings.xml. This requiresmaven-gpg-plugin3.2.0 or newer. See GPG. - Legacy AdoptOpenJDK distributions were removed. Use
temurininstead ofadoptoradopt-hotspot, andsemeruinstead ofadopt-openj9.
V5
- Upgraded the action runtime from Node 20 to Node 24. Self-hosted runners must use version
v2.327.1or later. See the runner release notes. - Added support for GraalVM Community and Tencent Kona.
- Expanded
java-version-filesupport with.sdkmanrcfiles and automatic distribution detection from SDKMAN and asdf vendor identifiers. - Added optional package-signature verification for Eclipse Temurin and Microsoft Build of OpenJDK downloads.
- Added
set-default: falsefor installing a JDK without changingJAVA_HOMEorPATH. - Improved dependency caching with separate Maven and Gradle wrapper caches, Maven extension-aware cache keys, and the
cache-primary-keyoutput. - Improved Maven and Java build behavior by preserving toolchain entries across repeated action invocations, suppressing transfer progress by default, generating non-interactive Maven settings, and matching
javaccompiler errors. - Renamed the
jdkFileinput tojdk-file; the old name remains available as a deprecated alias. - See the complete V5 release history for enhancements and fixes across all V5 releases.
Older versions
Warning
actions/setup-javaversionsv1throughv4are deprecated. Upgrade workflows toactions/setup-java@v5, the latest stable release.
Usage
Install Eclipse Temurin
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
- run: java --version
Install Microsoft Build of OpenJDK
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: microsoft
java-version: '25'
- run: java --version
Read the version from a file
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version-file: .java-version
- run: java --version
Supported version files are .java-version, .tool-versions, and .sdkmanrc. A .sdkmanrc file can also provide the distribution when it contains a recognized suffix, such as java=21.0.5-tem.
Use the newest stable Java
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: latest
- run: java --version
latest resolves the newest stable GA release from remote metadata rather than from the runner tool cache. Distributions that do not publish a release listing (such as oracle and graalvm) resolve the newest GA feature version from the Adoptium available-releases API and then request that version from their own catalog. latest is not supported with java-version-file, early-access versions, or distribution: jdkfile.
Inputs
| Input | Description | Default |
|---|---|---|
java-version |
Java version to install. Supports whole versions, semver ranges, early-access versions, and latest. Required unless java-version-file is set. |
|
java-version-file |
Path to .java-version, .tool-versions, or .sdkmanrc. Used when java-version is not set. |
|
distribution |
Java distribution keyword. Values are case-sensitive and must match one of the supported keywords below. Required unless java-version-file points to .sdkmanrc with a recognized distribution suffix. |
|
java-package |
Package variant such as jdk, jre, jdk+fx, jre+fx, jdk+crac, jre+crac, jdk+jmods, jdk+jcef, jre+jcef, jdk+ft, or jre+ft. Support varies by distribution. |
jdk |
architecture |
Package architecture. Canonical values are x86, x64, armv7, aarch64, ppc64le, ppc64, and s390x. Aliases ia32, amd64, arm, and arm64 are normalized. |
Runner architecture |
jdk-file |
Local compressed JDK archive. Requires distribution: jdkfile. |
|
check-latest |
Check remote metadata for the latest version satisfying the version spec before using the runner tool cache. | false |
force-download |
Always download Java and replace any matching version in the tool cache. | false |
set-default |
Add Java to PATH and set JAVA_HOME. When false, only version-specific JAVA_HOME_<major>_<arch> variables are set. |
true |
problem-matcher |
Register Java compiler and uncaught exception problem matchers. | true |
verify-signature |
Verify downloaded Java package signatures when supported. Currently supported for temurin and microsoft. |
false |
verify-signature-public-key |
ASCII-armored GPG public key to use for signature verification. Overrides the bundled key. | |
token |
Token for fetching GitHub.com-hosted version manifests, useful on GitHub Enterprise Server when unauthenticated requests are rate-limited. | ${{ github.token }} on GitHub.com; empty string on GHES |
cache |
Enable dependency caching for maven, gradle, or sbt. |
|
cache-jdk |
Cache downloaded JDK installations between jobs. When omitted, JDK caching is enabled only if cache is set. Set explicitly to true or false to override. |
Enabled when cache is set |
cache-dependency-path |
Dependency file paths used for cache key hashing. Supports globs and multiline values. | Auto-detected by package manager |
cache-path |
Cache paths to use instead of the package manager's default dependency cache path. Supports multiline values and exclusions. | |
cache-read-only |
Restore dependency, wrapper, and JDK caches without saving changes in the post step. | false |
server-id |
Maven repository ID used in generated settings.xml. |
github |
server-username-env-var |
Environment variable name for Maven repository username. | GITHUB_ACTOR |
server-password-env-var |
Environment variable name for Maven repository password or token. | GITHUB_TOKEN |
settings-path |
Directory where settings.xml is written. |
~/.m2 |
overwrite-settings |
Overwrite an existing settings.xml. |
true |
gpg-private-key |
GPG private key to import. | |
gpg-passphrase-env-var |
Environment variable name for the GPG private key passphrase. | GPG_PASSPHRASE when a key is set |
mvn-toolchain-id |
Maven Toolchain ID. When multiple Java versions are installed, the number of IDs must match the number of versions. | ${vendor}_${java-version} |
mvn-toolchain-vendor |
Maven Toolchain vendor value. | ${distribution} |
show-download-progress |
Keep Maven artifact download and transfer progress in logs. When false, the action adds -ntp to MAVEN_ARGS. |
false |
java-package: Supported package types arejdk,jre,jdk+fx,jre+fx,jdk+crac,jre+crac,jdk+jmods,jdk+jcef,jre+jcef,jdk+ft, andjre+ft. Availability varies by distribution.
Deprecated aliases jdkFile, server-username, server-password, and gpg-passphrase remain accepted for compatibility, but should be replaced with the current input names.
Outputs
| Output | Description |
|---|---|
distribution |
Distribution that was installed. |
version |
Actual Java version that was installed. |
path |
Installation path, also used for JAVA_HOME when set-default is enabled. |
cache-hit |
Whether an exact dependency cache match was restored. |
cache-primary-key |
Primary cache key computed for the selected package manager. Empty when caching is disabled or skipped. |
Supported distributions
| Keyword | Distribution | License |
|---|---|---|
corretto |
Amazon Corretto | License |
dragonwell |
Alibaba Dragonwell JDK | License |
graalvm |
Oracle GraalVM | License |
graalvm-community |
GraalVM Community | License |
jetbrains |
JetBrains Runtime | License |
kona |
Tencent Kona JDK | License |
liberica |
Liberica JDK | License |
liberica-nik |
Liberica Native Image Kit | License |
microsoft |
Microsoft Build of OpenJDK | License |
oracle |
Oracle JDK | License |
oracle-openjdk |
Oracle OpenJDK | License |
sapmachine |
SAP SapMachine JDK/JRE | License |
semeru |
IBM Semeru Runtime Open Edition | License |
temurin |
Eclipse Temurin | License |
zulu |
Azul Zulu OpenJDK | License |
jdkfile |
Custom JDK archive |
Note
Distribution availability, package variants, architectures, and version metadata differ by vendor. Check the vendor documentation when a specific version or platform matters.
Additional distribution notes:
- Oracle OpenJDK builds are archived after a limited number of releases and no longer receive security updates. To continue receiving security patches, use Oracle JDK or another vendor.
- Azul Zulu maps
arm64toaarch64when querying the Azul Metadata API. - GraalVM Community is available as
distribution: graalvm-communityfor stable JDK 17 and later releases. - On Ubuntu runners, commands executed with
sudodo not inherit theJAVA_HOMEandPATHset bysetup-javaand may fall back to the system-default JDK.
Supported version syntax
java-version accepts exact versions, version ranges, early-access versions, and latest.
| Syntax | Examples |
|---|---|
| Major version | 8, 11, 17, 21, 25 |
| Specific feature or patch version | 11.0, 11.0.4, 17.0, 8.0.282+8 |
| JEP 322 multi-field versions | 11.0.9.1, 18.0.1.1 |
| Early access | 15-ea, 15.0.0-ea, 27-ea |
| Latest stable GA release | latest |
When check-latest is false, the action first tries the runner tool cache for the requested distribution, package type, architecture, and version range. It downloads Java only when no matching cached version is found. When check-latest is true, the action checks remote metadata first and downloads if the cached version is not current.
GitHub-hosted runners primarily pre-cache Eclipse Temurin JDKs. See the installed Java versions for Ubuntu, Windows, and macOS. On a fresh GitHub-hosted runner, requests for other distributions usually miss the tool cache and resolve from remote metadata. For broad version ranges such as a major version (21, 25), this often behaves similarly to check-latest: true because the action downloads the latest available release that satisfies the range.
Download integrity and signatures
setup-java automatically verifies downloaded archive checksums when a selected distribution publishes an authoritative checksum. Automatic checksum verification currently applies to temurin, semeru, corretto, dragonwell, kona, sapmachine, graalvm, graalvm-community, zulu, oracle, oracle-openjdk, microsoft, and jetbrains.
Distributions or individual releases without an authoritative checksum continue to install normally, with the omission reported in debug logs. Installations resolved directly from the runner tool cache — including JDKs preinstalled on the runner image and JDKs installed by an earlier step of the same job — are not downloaded again and are not reverified, even when verify-signature: true is set. Use force-download: true to always download and verify the archive.
Use verify-signature: true to verify package signatures for distributions that support it. Currently supported distributions are temurin and microsoft; setting it for an unsupported distribution fails the workflow.
Caching
setup-java manages three kinds of caches. Each one is restored and saved as a separate cache entry.
| Cache | What it stores | Key based on | How it is enabled |
|---|---|---|---|
| Dependency cache | Downloaded dependencies, such as ~/.m2/repository, ~/.gradle/caches, or the sbt cache paths |
Runner OS, architecture, package manager, and a hash of the dependency files | Set cache to maven, gradle, or sbt |
| Wrapper caches | Maven and Gradle wrapper distributions (~/.m2/wrapper/dists, ~/.gradle/wrapper) |
Runner OS, architecture, wrapper cache name, and a hash of the wrapper properties | Set cache to maven or gradle |
| JDK cache | The downloaded JDK installation | Runner OS, architecture, distribution, package type, resolved version, release identity, and signature-verification identity | Enabled implicitly whenever cache is set, or explicitly with cache-jdk: true. Opt out with cache-jdk: false |
Set cache to maven, gradle, or sbt to cache dependencies with minimal configuration.
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
cache: maven
- run: mvn verify
The primary dependency cache key is setup-java-<runner-os>-<node-arch>-<package-manager>-<file-hash>, where <node-arch> is the runner's Node.js process architecture. The primary cache stores dependency directories such as ~/.m2/repository, ~/.gradle/caches, or the sbt cache paths. Its file hash is based on these files by default:
| Package manager | Files used for the primary dependency-cache key |
|---|---|
| Gradle | **/*.gradle*, **/gradle-wrapper.properties, buildSrc/**/Versions.kt, buildSrc/**/Dependencies.kt, gradle/*.versions.toml, **/versions.properties |
| Maven | **/pom.xml, **/.mvn/wrapper/maven-wrapper.properties, **/.mvn/extensions.xml |
| sbt | **/*.sbt, **/project/build.properties, **/project/**.scala, **/project/**.sbt |
Use cache-dependency-path to override the files used for key hashing, especially in monorepos:
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
cache: gradle
cache-dependency-path: |
sub-project/*.gradle*
sub-project/**/gradle-wrapper.properties
Use cache-path when the build tool stores dependencies outside the default location:
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
cache: maven
cache-path: |
/custom/maven/repository
!/custom/maven/repository/**/*.lastUpdated
- run: mvn -Dmaven.repo.local=/custom/maven/repository verify
cache-path changes what is restored and saved, but not the cache key. Jobs that should share a cache key must use the same OS, architecture, package manager, dependency files, and cache paths.
Wrapper caches
Maven and Gradle wrapper distributions are restored and saved as additional cache entries, separate from the primary dependency cache. These entries have their own keys in the form setup-java-<runner-os>-<node-arch>-<wrapper-cache-name>-<file-hash>.
| Package manager | Wrapper cache name | Cached path | Files used for wrapper-cache key |
|---|---|---|---|
| Maven | maven-wrapper |
~/.m2/wrapper/dists |
**/.mvn/wrapper/maven-wrapper.properties |
| Gradle | gradle-wrapper |
~/.gradle/wrapper |
**/gradle-wrapper.properties |
These wrapper caches are independent from dependency caches, so they remain useful even when dependency files change frequently. The wrapper properties are also part of the Maven and Gradle primary dependency-cache key because wrapper changes can affect how dependencies are resolved, but the wrapper distribution files themselves are stored in the separate wrapper cache entries above.
For advanced Gradle caching features such as build output caching, configuration cache support, encrypted cache storage, cleanup, and fine-grained cache control, consider gradle/actions/setup-gradle.
Caching JDK installations
The JDK cache stores the downloaded JDK installation so later runs skip the download. It is enabled implicitly whenever dependency cache is set, so most workflows that cache dependencies are already caching the JDK. Set cache-jdk: true to enable it without dependency caching, or cache-jdk: false to opt out while keeping dependency caching. With neither cache nor cache-jdk set, nothing is cached.
Important
Because JDK caching is on by default whenever
cacheis set, review Caching JDK installations for the fullcache/cache-jdkmatrix, cache identity and storage impact.
Read-only caches
Set cache-read-only: true to restore dependency, wrapper, and JDK caches without saving changes in the post action. This is useful for pull requests, merge queues, short-lived branches, and matrix fan-out jobs that should only consume caches produced elsewhere.
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
cache: maven
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
For matrix fan-out, seed the cache once and make matrix jobs read-only consumers:
jobs:
seed-cache:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
cache: maven
- run: mvn dependency:go-offline dependency:resolve-plugins
build:
needs: seed-cache
runs-on: ubuntu-latest
strategy:
matrix:
goal: [test, verify, package]
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
cache: maven
cache-read-only: true
- run: mvn ${{ matrix.goal }}
Cache segment restore timeout
Cache downloads are split into segments. To reduce the chance of a stuck segment blocking a workflow, set SEGMENT_DOWNLOAD_TIMEOUT_MINS:
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: '5'
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
cache: gradle
- run: ./gradlew build --no-daemon
Multiple JDKs and Maven toolchains
Install multiple Java versions by providing a multiline java-version value. All configured JDKs are installed. The last one added to PATH becomes the default.
steps:
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: |
8
11
17
21
25
Other installed JDKs are available through version-specific variables such as JAVA_HOME_17_X64. To use a specific version later in the job, set JAVA_HOME and prepend its bin directory to PATH.
setup-java writes a Maven Toolchains declaration for each installed JDK. When multiple JDKs are installed, the declaration contains all of them. Customize the generated toolchain values with mvn-toolchain-id and mvn-toolchain-vendor.
Testing with a Java matrix
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
java: ['8', '11', '17', '21', '25']
name: Java ${{ matrix.java }}
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: ${{ matrix.java }}
- run: java --version
- run: mvn verify
Publishing packages
setup-java generates Maven settings.xml and Maven Toolchains configuration. For Gradle publishing, it installs Java for the workflow; the Gradle build file remains responsible for reading credentials from environment variables.
Maven
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
server-id: github
server-username-env-var: GITHUB_ACTOR
server-password-env-var: GITHUB_TOKEN
- run: mvn --batch-mode deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GPG signing
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '25'
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
gpg-passphrase-env-var: GPG_PASSPHRASE
- run: mvn --batch-mode deploy
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
Maven GPG signing requires maven-gpg-plugin 3.2.0 or newer because setup-java passes the passphrase through gpg.passphraseEnvName.
Recommended permissions
When using the setup-java action in your GitHub Actions workflow, it is recommended to set the following permissions to ensure proper functionality:
permissions:
contents: read # access to check out code and install dependencies
Publishing workflows may require additional permissions depending on the target registry.
Advanced usage
See advanced usage for detailed examples:
- Selecting a Java distribution
- Installing custom Java package types
- Package compatibility
- Ensuring the Maven cache is complete
- Caching JDK installations
- Platform and architecture compatibility
- Installing custom Java architecture
- Installing a JDK without setting it as default
- Installing Java from a local file
- Testing against different Java distributions
- Testing against different platforms
- Publishing using Apache Maven
- Apache Maven with a settings path
- Maven transfer progress
- Java problem matcher
- Publishing using Gradle
- Hosted tool cache
- Modifying Maven Toolchains
- Java version files
- Self-signed certificates and internal CAs on GitHub Enterprise
License
The scripts and documentation in this project are released under the MIT License.
Contributions
Contributions are welcome. See our Contributor's Guide.
Code of Conduct
👋 Be nice. See our code of conduct