Skip to content

Enabling Java preview features

Fred Bricon edited this page Mar 27, 2024 · 10 revisions

Under the hood, instead of javac, vscode-java uses ECJ, a Java 22 compiler provided by Eclipse JDT. It is used to compile against all other versions of Java. But the ECJ compiler only supports the latest JDK release when it comes to preview features. It means that, with the latest vscode-java release, preview features can not be enabled for projects compiling against Java 19 (or older), even if you configured the proper runtime. Those projects need to be updated to use Java 22 in vscode-java.

It's recommended you configure the java.configuration.runtimes preference in your user's settings.json:

"java.configuration.runtimes": [
  {
    "name": "JavaSE-22",
    "path": "/path/to/jdk-22",
    "default": true
  },
],

Now, depending on the style of Java projects you use, there are different ways to enable preview features.

Standalone Java files

When you open standalone Java files (i.e. which have no Eclipse/Maven/Gradle settings), preview features are enabled by default, without warnings, if vscode-java was started with a JDK 22 or JavaSE-22 is set to be the default in java.configuration.runtimes.

Maven projects

Maven projects need to have the --enable-preview flag added to the maven-compiler-plugin configuration, in their pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>foo.bar</groupId>
  <artifactId>demo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
 <properties>
  	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.13.0</version>
        <configuration>
          <release>22</release>
          <compilerArgs>--enable-preview</compilerArgs>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Eclipse projects

Eclipse projects need to add the the following preferences to .settings/org.eclipse.jdt.core.prefs:

eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=22
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=22
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=22

org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=enabled
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore

Gradle projects

⚠️ Gradle 8.7 minimum is required to build Java 22 projects.

Gradle projects can also maintain the same .settings/org.eclipse.jdt.core.prefs file. Alternatively, adding an eclipse.jdt.file.withProperties hook in build.gradle is possible, but requires the gradle compileJdt task to be invoked manually, as Buildship, the underlying Gradle integration tool, doesn't invoke it :

plugins {
    // Apply the java-library plugin to add support for Java Library
    id 'java-library'
    id 'eclipse'
}
sourceCompatibility = JavaVersion.VERSION_22
targetCompatibility = JavaVersion.VERSION_22

compileJava {
    options.compilerArgs += ["--enable-preview"]
}
compileTestJava {
    options.compilerArgs += ["--enable-preview"]
}
//Buildship doesn't use that hook (https://discuss.gradle.org/t/when-does-buildship-eclipse-customization-run/20781/2)
//you need to run `gradle eclipse` separately
eclipse.jdt.file.withProperties { props ->
    props['org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures']= 'enabled'
    props['org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures']= 'ignore'
}

test {
    jvmArgs '--enable-preview'
}