Configuring the JDK Version in a DevContainer

A JVM project must compile against a known JDK, and the editor must analyze against the same one. This page pins the JDK via the Java Feature and points the Java language server at it, so the build and the editor never disagree about the Java version.

Prerequisites

You need a Java devcontainer and the target JDK version.

  • The Java Feature available.
  • The JDK version your project targets.
  • The Java extension pack in the container.

JDK prerequisitesYou need the pinned Feature, the LS java.home, runtime config, and a check.Java Featureversion pinnedjava.homeLS points at itRuntimesconfiguredVerifyjava -version

Step-by-Step Implementation

  1. Pin the JDK via the Feature.
{
  "features": { "ghcr.io/devcontainers/features/java:1": { "version": "21" } },
  "remoteUser": "vscode"
}
  1. Point the language server at that JDK.
{ "customizations": { "vscode": { "settings": {
  "java.jdt.ls.java.home": "/usr/local/sdkman/candidates/java/current"
} } } }
  1. Configure runtimes if you target multiple JDKs.
{ "customizations": { "vscode": { "settings": {
  "java.configuration.runtimes": [ { "name": "JavaSE-21", "path": "/usr/local/sdkman/candidates/java/current", "default": true } ]
} } } }
  1. Verify the versions match.
java -version   # matches the pinned Feature and the LS java.home

JDK routingA pinned JDK plus a matching language-server java.home keeps the editor and build aligned.Feature-pinned JDKthe build's JavaLS java.homethe editor's JavaRuntimes configmulti-JDK supportResulteditor == build JDK

Common Pitfalls

JDK mismatches come from an unpinned Feature or a wrong java.home.

JDK triageA triage path from a JDK mismatch to aligned editor and build.Is the JDK pinned on the Feature?NOSet the Feature versionDoes the LS use the same JDK?YESRuntimes configuredEditor and build agree

SymptomRoot CauseRemediation
Editor errors differ from buildLS on a different JDKSet java.jdt.ls.java.home to the JDK
Wrong Java version at buildFeature version unpinnedPin the Java Feature version
Multi-module targets differNo runtimes configConfigure java.configuration.runtimes
Preview features failJDK too oldPin a newer JDK version

Conclusion

Pin the JDK on the Java Feature so the build compiles against a known version, and point the language server's java.home at the same JDK so the editor analyzes it too. When both use one Java, the editor's verdict matches the build's.

Pin and route JDKPin the JDK for the build and route the language server at the same JDK.Pin (build)Feature versionWrapper toolCommitted configRoute (editor)jdt.ls java.homeruntimes listDefault runtime

FAQ

How do I pin the JDK version? Set the version on the Java Feature (ghcr.io/devcontainers/features/java with "version": "21"). Every rebuild then installs that exact JDK, so the build compiles against a known Java version rather than whatever happens to be installed.

Why does the editor use a different Java than my build? The Java language server has its own java.home setting. If it isn't pointed at the container's JDK, it analyzes against a different Java. Set java.jdt.ls.java.home (and java.configuration.runtimes) to the Feature-installed JDK so both agree.

Can I target multiple JDKs in one container? Yes — install the JDKs you need and list them in java.configuration.runtimes, marking one default. Modules can then target different Java versions, and the language server resolves each against the correct runtime.