
Image by Kev from Pixabay
Installing the newly released JDK 21 LTS release on MacOS is rather straightforward, but requires a couple of non-intuitive steps; also, current support for Gradle builds is “tentative” at best, so we will show below a simple way to upgrade your Spring Boot application(s).
Download the JDK from here (if you are using a recent-ish MacBookPro with Apple Silicon, M1 or M2, choose the macOS / AArch64 variant; for older versions with Intel silicon, macOS / x64 should work just fine).
The JDKs are installed (on MacOS) in /Library/Java/JavaVirtualMachines:
└─( lsjava
21 /Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home
20.0.2 /Library/Java/JavaVirtualMachines/jdk-20.0.2.jdk/Contents/Home
17.0.2 /Library/Java/JavaVirtualMachines/jdk-17.0.2.jdk/Contents/Home
where
alias lsjava='/usr/libexec/java_home -X | \
plutil -convert json -o - - | \
jq ".[] | .JVMVersion + \" \" + .JVMHomePath" | \
sed "s/\"//g"'
is a little shortcut of mine, to quickly find what’s where (on my machine I also keep older JDKs, including 8 and 11, the main LTS releases).
Once downloaded and unzipped the tarball, move the folder to its final resting place and update JAVA_HOME:
└─( sudo mv Downloads/jdk-21.jdk /Library/Java/JavaVirtualMachines
└─( export JAVA_HOME=$(/usr/libexec/java_home -v 21)
└─( java -version
openjdk version "21" 2023-09-19
OpenJDK Runtime Environment (build 21+35-2513)
OpenJDK 64-Bit Server VM (build 21+35-2513, mixed mode, sharing)
to make the change “stick,” you may want to add that export JAVA_HOME line in your .zshrc file.
Finally, update IntelliJ installed JDKs:

Right-click on the module name in the Project view and select Open Module Settings
The most recent Gradle release (8.4) does support building using Java 21, so, the first step is to upgrade the downloaded “wrapper”: change to your project’s folder and run:
./gradlew wrapper --gradle-version=8.4 --distribution-type=bin
which will nicely update the entry in your gradle/gradle-wrapper.properties:
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
However, that won’t really help much, and depending on your setup/configuration/dependencies, trying to run ./gradlew clean build will most likely fail.
In my simple Spring Boot CLI demo app, I updated my build.gradle to look as follows (the full commit is here):
plugins {
id 'application'
id 'org.springframework.boot' version '3.1.4'
id 'io.spring.dependency-management' version '1.1.3'
id 'java'
}
java {
sourceCompatibility = '21'
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
ext {
// see note below
lombokVersion = "1.18.30"
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// Lombok
compileOnly "org.projectlombok:lombok:${lombokVersion}"
annotationProcessor "org.projectlombok:lombok:${lombokVersion}"
// For the @PostConstruct annotation
implementation 'javax.annotation:javax.annotation-api:1.3.2'
}
Simplified build.gradle to support JDK 21
This is all pretty self-explanatory (and rather unsurprising) apart from the Lombok needed upgrade – any version prior to .30 will cause a rather confusing error:
Fatal error compiling: java.lang.NoSuchFieldError:
Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field 'com.sun.tools.javac.tree.JCTree qualid'
which is 🤷🏼
Having done all the above:
└─( gw clean build test
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
> Task :app:test
BUILD SUCCESSFUL in 2s
15 actionable tasks: 15 executed





Leave a comment