44

I would like to set the required Java version (e.g. 7 or 8) in my Gradle build file without having to specify the actual path to a local JDK installation.

Is this possible?

Michael
  • 41,989
  • 11
  • 82
  • 128
pditommaso
  • 3,186
  • 6
  • 28
  • 43
  • You're looking for the equivalent of maven's enforcer plugin for jvm version, right? https://github.com/kordamp/enforcer-gradle-plugin/ – Antony Stubbs Aug 18 '20 at 06:27

5 Answers5

37

This feature was just added to Gradle 6.7 as Java toolchains:

// build.gradle.kts

plugins {
    id("java-library") // or id("application")
}

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(11))
    }
}

With this in place Gradle will automatically download & use the appropriate JDK (using AdoptOpenJDK by default) for the specified Java version.

CletusW
  • 3,890
  • 1
  • 27
  • 42
  • Do you know how to select a specific revision of the JDK, for example Java 8 revision 261? I cannot find the documentation of JavaLanguageVersion. :-( – Matthias Dec 01 '20 at 07:52
  • 1
    Nevermind. I found https://docs.gradle.org/current/javadoc/org/gradle/jvm/toolchain/JavaLanguageVersion.html. Seems like it's not possible at the moment. But the underlying infrastructure of Gradle seems to be prepared for fetching a specific revision.I get the following exception: "Unable to download toolchain. This might indicate that the combination (version, architecture, release/early access, ...) for the requested JDK is not available." – Matthias Dec 01 '20 at 08:21
22

TLDR; Thanks @franklin-yu "targetCompatibility = '1.7' -> your user can compile with 8 and run with 7."

See Gradle, "sourceCompatibility" vs "targetCompatibility"?

targetCompatibility = '1.7' does the trick for e.g. Java 7

Use sourceCompatibility = '1.7' for the language level

Community
  • 1
  • 1
dhfsk
  • 281
  • 1
  • 8
  • 2
    Also, if `targetCompatibility` is not specified, it defaults to `sourceCompatibility`. – fge Jan 09 '15 at 13:45
  • 3
    No, these options set the target source code and byte-code compatibility. I need instead to specify what JDK version to use to carry out the compilation. – pditommaso Jan 09 '15 at 13:50
  • Gradle uses the JDK which it finds in your PATH, to select a different one set JAVA_HOME to the desired path – dhfsk Jan 09 '15 at 14:32
  • you can cross compile for an older JVM just by setting the targetCompatibility. you dont need the a specific JDK version. This naturally only works for older language versions. – dhfsk Jan 09 '15 at 14:41
  • In my build I've specified both `targetCompatibility` and `sourceCompatibility` however when a user download and compile the project with JDK 8 but, for any reason, run with Java 7, it will result in the following exception: java.lang.ClassNotFoundException: java.util.function.BiFunction at java.net.URLClassLoader$1.run(URLClassLoader.java:366) ~[na:1.7.0_67] at java.net.URLClassLoader$1.run(URLClassLoader.java:355) ~[na:1.7.0_67] at java.security.AccessController.doPrivileged(Native Method) ~[na:1.7.0_67] – pditommaso Jan 09 '15 at 15:54
  • 2
    `BiFunction` is a new addition to the Java 8 JDK. If your project depends on that class it cannot be run on a < Java 8 JRE. – Mark Vieira Jan 10 '15 at 03:52
  • No, I'm not using the `BiFunction` interface, but I guess it is referenced from some library when my project is compiled with Java 8. This why I was asking a way to stick the Java runtime version in the Gradle build – pditommaso Jan 15 '15 at 15:37
  • 1
    @Paulecci, if you have `targetCompatibility = '1.7'` in your `build.gradle`, your user can compile with 8 and run with 7. – Franklin Yu Apr 27 '16 at 01:07
  • @pditommaso ... Yes I have the same problem. Build and compile target 1.7. When I run or debug from Gradle, it will use the local 1.8 `JAVA_HOME` runtime. That seems OK but, the debugger _correctly_ loads 1.7 SDK sources and they are NOT the same as the 1.8 JDK executiing. _grrr_ – will Nov 08 '17 at 00:33
13

You can try this:

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

tasks.withType<JavaCompile> {
    options.compilerArgs.addAll(arrayOf("--release", "8"))
}

This will also give JDK compliance to you. You can also see the following related issues:

Rosberg Linhares
  • 3,537
  • 1
  • 32
  • 35
5

In the build.gradle file, add the following two lines:

sourceCompatibility = '1.8'
targetCompatibility = '1.8'

The targetCompatibility defines the generated JVM bytecode version (this is the version that users of your application need). The sourceCompatibility defines which source code constructs are allowed (e.g. you need Java 1.8 or higher to use lambda expressions in source code).

Source

Pieter12345
  • 1,713
  • 1
  • 11
  • 18
3

Based on the answer of CletusW. In windows 10, it seems that the new installed Java will not be chosen automatically, so I check it manually.

apply plugin: 'java'
java.toolchain.languageVersion = JavaLanguageVersion.of(15)  // auto install



// check JDK version
if (!System.getProperty("java.home").contains(java.toolchain.languageVersion.get().toString())) {
    def msg = ('JDK in this project: ' + System.getProperty('java.home') + '\n' +
            'In this project, you should use JDK-' + java.toolchain.languageVersion.get())
    throw new GradleException(msg)
}

Jess Chen
  • 3,136
  • 1
  • 26
  • 35
  • I have Gradle 7.2, the auto-download just starts. Which I didn't like because I want to check the Java in-use or to use an existing installed version. – will Sep 13 '21 at 00:47