Setting Up Java 17: JDK Options, Tooling, and IDE Configuration
JDK Distribution Options
Multiple vendors ship Java 17 JDK builds. All pass the TCK (Technology Compatibility Kit) — they are functionally equivalent for development.
| Distribution | Provider | Notes |
|---|---|---|
| Eclipse Temurin | Adoptium / Eclipse | Recommended default; fully open-source |
| Amazon Corretto | AWS | Free; optimized for AWS Lambda and EC2 |
| Microsoft Build of OpenJDK | Microsoft | Windows and Azure optimized |
| Oracle JDK 17 | Oracle | Free for development; commercial license for production |
| Azul Zulu | Azul | Commercial support available; free binaries |
| GraalVM CE 22.3+ | Oracle | Adds native-image; based on Java 17 |
Recommendation: Use Eclipse Temurin 17 for development and CI. It is the most widely used OpenJDK build, fully open-source, and supported by the Eclipse Foundation.
Installing Java 17
Option 1: SDKMAN (Recommended — Manages Multiple JDKs)
SDKMAN lets you install and switch between multiple JDK versions with a single command.
Install SDKMAN:
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
List available Java 17 builds:
sdk list java | grep "17"
Install Eclipse Temurin 17:
sdk install java 17.0.11-tem
Set as default:
sdk default java 17.0.11-tem
Switch to Java 17 for the current shell only:
sdk use java 17.0.11-tem
Switch back to another version:
sdk use java 21.0.3-tem
Option 2: Homebrew (macOS)
brew install --cask temurin@17
# Set JAVA_HOME
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
echo 'export JAVA_HOME=$(/usr/libexec/java_home -v 17)' >> ~/.zshrc
Option 3: Direct Download
Download from adoptium.net — select Java 17, your OS, and architecture. Extract and set JAVA_HOME.
Verify Installation
java -version
# openjdk version "17.0.11" 2024-04-16
# OpenJDK Runtime Environment Temurin-17.0.11+9 (build 17.0.11+9)
# OpenJDK 64-Bit Server VM Temurin-17.0.11+9 (build 17.0.11+9, mixed mode, sharing)
javac -version
# javac 17.0.11
Maven Configuration
Set Compiler to Java 17
<!-- pom.xml -->
<properties>
<java.version>17</java.version>
<maven.compiler.release>17</maven.compiler.release>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
Use <release> (not <source> and <target>) — it correctly prevents using APIs from newer JDKs and newer class file formats simultaneously.
Enabling Preview Features in Maven
Article 8 uses Pattern Matching for switch, which is a preview feature in Java 17. To compile and test preview features:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<release>17</release>
<compilerArgs>
<arg>--enable-preview</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
</plugins>
</build>
Preview features also require --enable-preview at runtime:
java --enable-preview -jar myapp.jar
Minimum Maven Version
Use Maven 3.8.1 or later with Java 17. Earlier versions have issues with the module system and strong encapsulation.
mvn -version
# Apache Maven 3.9.6
Gradle Configuration
Kotlin DSL (build.gradle.kts)
plugins {
java
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
tasks.withType<JavaCompile> {
options.release = 17
}
Using a toolchain is preferred over setting sourceCompatibility — it ensures the correct JDK is used for compilation even if your local default JDK is different.
Enabling Preview Features in Gradle
tasks.withType<JavaCompile> {
options.release = 17
options.compilerArgs.add("--enable-preview")
}
tasks.withType<Test> {
jvmArgs("--enable-preview")
}
tasks.withType<JavaExec> {
jvmArgs("--enable-preview")
}
Groovy DSL (build.gradle)
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
compileJava {
options.release = 17
}
Minimum Gradle Version
Use Gradle 7.3 or later for Java 17 support. Gradle 8.x is recommended.
IntelliJ IDEA Configuration
Set Project SDK
- File → Project Structure → Project
- Set SDK to Java 17 (add it with + if not listed)
- Set Language level to 17 - Sealed classes, always-strict floating-point semantics
For preview features, set Language level to 17 (Preview) — Pattern matching for switch, ….
Set Module SDK
- File → Project Structure → Modules
- For each module, set Language level to match the project level
Maven / Gradle Auto-Sync
IntelliJ reads the release setting from your pom.xml or build.gradle.kts and configures the project automatically after a sync:
- Maven: Maven tool window → Reload All Maven Projects (or
Cmd+Shift+O) - Gradle: Gradle tool window → Reload All Gradle Projects
Enable Preview Features in IntelliJ
Set the language level to 17 (Preview) in Project Structure. IntelliJ will then recognize preview feature syntax without compilation errors in the editor.
Recommended IntelliJ Plugins
| Plugin | Purpose |
|---|---|
| SonarLint | Static analysis |
| CheckStyle-IDEA | Code style enforcement |
| Lombok | If still using Lombok alongside records |
VS Code Configuration
Install the Extension Pack
Install Extension Pack for Java by Microsoft:
code --install-extension vscjava.vscode-java-pack
This includes Language Support for Java, Debugger for Java, Test Runner, Maven for Java, and Gradle for Java.
Configure Java Home
In .vscode/settings.json (project-level):
{
"java.jdt.ls.java.home": "/Users/yourname/.sdkman/candidates/java/17.0.11-tem",
"java.configuration.runtimes": [
{
"name": "JavaSE-17",
"path": "/Users/yourname/.sdkman/candidates/java/17.0.11-tem",
"default": true
}
]
}
Or globally in settings.json (Cmd+Shift+P → “Open User Settings (JSON)”):
{
"java.home": "/Users/yourname/.sdkman/candidates/java/17.0.11-tem"
}
Enable Preview Features in VS Code
Add to .vscode/settings.json:
{
"java.compile.nullAnalysis.mode": "automatic",
"java.configuration.updateBuildConfiguration": "automatic"
}
Preview syntax is handled by the language server when your pom.xml or build.gradle.kts has --enable-preview configured.
Running Java 17 Programs
Compile and Run
# Compile
javac --release 17 Hello.java
# Run
java Hello
# With preview features
javac --release 17 --enable-preview Hello.java
java --enable-preview Hello
Compile a Single-File Program
Java 11+ supports running a single .java file directly:
java Hello.java
With preview features:
java --enable-preview --source 17 Hello.java
Using jshell
JShell (Java 9+) supports Java 17 features interactively:
jshell --enable-preview
| Welcome to JShell -- Version 17.0.11
jshell> record Point(int x, int y) {}
| created record Point
jshell> var p = new Point(3, 4)
p ==> Point[x=3, y=4]
jshell> p.x()
$3 ==> 3
JShell is the fastest way to experiment with new Java features without creating a full project.
Verifying the Setup
Create a file Java17Check.java that exercises several Java 17 features:
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
public class Java17Check {
sealed interface Shape permits Circle, Rect {}
record Circle(double radius) implements Shape {}
record Rect(double w, double h) implements Shape {}
public static void main(String[] args) {
// Records
var p = new Circle(5.0);
System.out.println("Record: " + p);
// Text block
String json = """
{"shape": "circle", "radius": 5.0}
""";
System.out.println("Text block: " + json.strip());
// Pattern matching for instanceof
Object obj = "hello";
if (obj instanceof String s && s.length() > 3) {
System.out.println("Pattern match: " + s.toUpperCase());
}
// Switch expression
Shape shape = new Rect(3, 4);
double area = switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rect r -> r.w() * r.h();
};
System.out.println("Switch expression area: " + area);
// Enhanced PRNG
RandomGenerator rng = RandomGeneratorFactory.of("L64X128MixRandom").create();
System.out.println("Random (LXM): " + rng.nextInt(100));
}
}
Compile and run:
javac --release 17 Java17Check.java
java Java17Check
Expected output:
Record: Circle[radius=5.0]
Text block: {"shape": "circle", "radius": 5.0}
Pattern match: HELLO
Switch expression area: 12.0
Random (LXM): 47
If you see this output, your Java 17 environment is correctly configured.
Common Setup Issues
error: --release: target release 17 conflicts with default source release 11
Your Maven/Gradle is still using an old JDK. Set JAVA_HOME correctly:
export JAVA_HOME=$(sdk home java 17.0.11-tem)
mvn clean compile
--add-opens Errors
If you see InaccessibleObjectException during tests, a dependency is using internal JDK APIs. Add to Surefire configuration:
<configuration>
<argLine>--add-opens java.base/java.util=ALL-UNNAMED</argLine>
</configuration>
See Article 11 for a complete guide to strong encapsulation and how to fix these errors.
Preview Feature Compile Error
error: preview feature is disabled by default
Add --enable-preview to both compilerArgs (for javac) and argLine (for JUnit/Surefire at runtime). Both flags are required.
What’s Next
Article 3: Text Blocks (JEP 378) covers Java’s multiline string literal — how to write clean, readable embedded JSON, SQL, HTML, and YAML in Java code.