Automatically provision specific versions of JDKs for Gradle tasks that require JDKs (JavaCompile
, Test
, JavaExec
etc) . Choose from a variety of different JDK vendors which can be automatically installed on multiple OSs.
Gradle has a built-in concept of auto-provisioning Java Toolchains, which will automatically install JDKs if they do not exist on system running Gradle, however it's lacking in some aspects:
- Gradle always uses AdoptOpenJDK/Adoptium.
- You may prefer a different JDK vendor. We use Azul Zulu for their MTS support. It is important to us to develop and test with the same JDK we use in prod.
- Adoptium does not provide macos
aarch64
for Java 11, which we need for Apple Silicon Macbooks.
- Once Gradle finds an appropriate JDK on disk for that Java language version, it is always used and never updated.
- As a company with tens of millions of lines of Java, we often bump into JVM bugs. It's highly desirable we test and deploy using the exact same version of JDKs.
- Similarly, it's important to us that the exact same JDK versions are used on local machines as well as CI.
- Gradle does not handle JDK CA certificates.
- Many companies use TLS interception when network calls are made outside their corporate network. Gradle provides no way to install the relevant CA certificates into auto-provisioned JDKs. This means they cannot be used in such an environment, or require manual patching.
- You cannot easily set up a mirror for auto-provisioned JDK downloads.
- There's a Gradle property you can set to change to server base uri, but this still leaves you writing and maintaining a service that replicates the adoptium api.
- An internal corporate mirror can be 100x faster than a public one, especially for CI builds.
gradle-jdks
solves all of these problems:
- You can choose your favoured JDK vendor.
- Use the same JDK version for representative, reproducible builds on dev machines and in CI.
- Automatically add JDK CA certificates.
- Point to an internal mirror for JDKs.
Palantirians: you probably shouldn't use this plugin directly - either use gradle-jdks-latest
for OSS or gradle-jdks-internal
for internal projects which will set everything up for you.
First, you must apply the plugin. In the root project, Either use the new plugin syntax:
plugins {
id 'com.palantir.jdks' version '<latest version>'
}
or the old buildscript method:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.palantir.gradle.jdks:gradle-jdks:<latest-version>'
}
}
apply plugin: 'com.palantir.jdks'
Next up comes configuring the JDKs plugin:
jdks {
// Required: For each Java major version you use, you need to specify
// a distribution and version.
jdk(11) {
distribution = 'azul-zulu'
jdkVersion = '11.54.25-11.0.14.1'
}
jdk(17) {
distribution = 'amazon-corretto'
jdkVersion = '17.0.3.6.1'
}
// Optional: For each distribution, you can set a base url for a
// mirror to use instead of the default public mirror.
// Default: Whatever mirror is publicly provided by the vendor
jdkDistribution('azul-zulu') {
baseUrl = 'https://internal-corporate-mirror/azul-zulu-cdn-mirror'
}
// Optional: You can specify CA certs which will be installed into
// the extracted JDK to work with TLS interception.
// Default: No CA certs are added.
caCerts.put 'corporate-tls-cert', '''
-----BEGIN CERTIFICATE-----
// snip
-----END CERTIFICATE-----
'''.stripIndent(true)
// Optional: Where to store the JDKs on disk. You almost certainly
// do not need to change this.
// Default: $HOME/.gradle/gradle-jdks
jdkStorageLocation = System.getProperty("user.home") + '/custom/location'
}
Behind the scenes, gradle-jdks
applies com.palantir.baseline-java-versions
(another gradle plugin - more docs in link) to handle configuring the Java language versions. You will need to configure this plugin as well to tell it what Java language versions:
// Read the docs at https://github.com/palantir/gradle-baseline#compalantirbaseline-java-versions
javaVersions {
libraryTarget = 11
distributionTarget = 17
}
Supported JDK distribution can be found here.
New JDK distributions are easily added - you just need to:
- Add an entry to
JdkDistributionName
- Add a
JdkDistribution
- Azul Zulu example. - Add the JDK distribution here.
- Write some tests to check the path is being built correctly - Azul Zulu example.
- Make a PR.
- Run the Gradle wrapper/daemon with a certain JDK
- This plugin will only run common tasks that require JDKs, like
JavaCompile
,Test
,JavaExec
,GroovyCompile
etc (the aforementionedcom.palantir.baseline-java-versions
does this). - The daemon itself still requires a preinstalled JDK.
- In future, we hope to implement this feature, although it is not currently scheduled to be worked on.
- This plugin will only run common tasks that require JDKs, like
If you run you gradle invocation with --info --rerun-tasks
, the JDK will be visible in the output:
$ ./gradlew compileJava --info --rerun-tasks
> Task :my-project:compileJava
Compiling with toolchain '/Users/username/.gradle/gradle-jdks/azul-zulu-17.34.19-17.0.3-a3ceab47882436a6'.
gradle-jdks-latest
applies this plugin and configures the latest JDK releases - primarily exists for Palantir use, enforcing consistency across our open-source projects.