Reputation: 12668
Gradle 6.7 introduced Java toolchains.
In the documentation, they state that Gradle chooses a JRE/JDK matching the requirements of the build ... By default, Gradle prefers installed JDKs over JREs... (from docs.gradle.org: Toolchains for JVM projects).
Thus, the JDK is chosen if we have both, JRE and JDK, installed.
Problem:
Imagine that the user only has a JRE installed.
Yet, we want to run our application via Gradle (JavaExec
task) using a Java toolchain, but have to ensure that a JDK is used for running because this application relies on tools.jar
, which is not part of a JRE.
Question:
Is it possible to force Gradle to use a JDK for all tasks (including running / launching), not just for compiling, when using a Java toolchain? (see following minimal example with comment)
// This build.gradle should ensure that the application is run using a JDK of version 9
plugins {
id 'application'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(9)
// QUESTION: How to force JDK here? <------
}
}
// for JavaExec task runJar
tasks.withType(JavaExec).configureEach {
javaLauncher = javaToolchains.launcherFor(java.toolchain)
}
task runJar(type: JavaExec) {
classpath = files(jar.archiveFile)
}
...
Upvotes: 2
Views: 7455
Reputation: 4603
For those of us without internet on build machines per business requirement, sigh, https://docs.gradle.org/current/userguide/toolchains.html describes Selecting toolchains by vendor:
java {
toolchain {
...
vendor = JvmVendorSpec.ADOPTIUM // or vendor = JvmVendorSpec.matching("Private Build") in my case. find the Vendor = value you need with ./gradlew -q javaToolchains
}
}
or even complete Custom toolchain locations:
org.gradle.java.installations.fromEnv=JDK8,JRE17
//from env vars
org.gradle.java.installations.paths=/custom/path/jdk1.8,/shared/jre11
Upvotes: 3
Reputation: 12668
The solution I finally came up with:
I now use org.gradle.java.installations.auto-detect=false
stored in a settings.gradle
file in my project. This ignores any locally installed Java versions when using Java toolchains in Gradle.
Thus, it will download a suitable JDK on the first run, and will reuse this JDK on future runs.
Upside: We ensure that even if a local JRE exists, we download a JDK (e.g., we can be sure that tools.jar
exists).
Downside: We also download a JDK if a matching one would exist on the machine.
Upvotes: -2
Reputation: 76799
One always has to add rt.jar
first:
task runJar(type: JavaExec) {
classpath = files(new File(System.getProperty('java.home') + File.separator + 'lib' + File.separator + 'rt.jar'))
classpath += files(jar.archiveFile)
...
}
runJar.onlyIf {
new File(System.getProperty('java.home') + File.separator + 'lib' + File.separator + 'rt.jar')).exists()
}
This probably would still require a mainClassName
inside jar.archiveFile
. With JavaExec
one can set up whatever environment
variable ...incl. JAVA_HOME
, so this could be alternated per task. But one can as well use an Exec
task on then directly run java
-jar some.jar
.
I wouldn't even be too certain, that these "runtime only" JRE distributions still exist?
All I know is that there is no tools.jar
Upvotes: -1
Reputation: 23
What is the tool you are using? If it is IntelliJ, then
A feature in IntelliJ that where it would look up if java tool chain is configured and if it is, make it impossible for me to have mismatching configuration within:
Run configurations Project Structure > Project SDK Project Structure > Project Language Level
Upvotes: 0