9 min read

Fixing Java: Error: Release version X not supported

Introduction

While importing or running a Java application, you might face different versions of this error as below.

Error: java: release version 17 not supported
Error: java: invalid target release: 17

With different versions of Java such as,

Error: java: release version 11 not supported
Error: java: release version 19 not supported
...etc

Error: java: invalid target release: 11
Error: java: invalid target release: 21
...etc

In IntelliJ IDEA, complete error might look like this.

invalid target release: 11

Module maven-test SDK 1.8 is not compatible with the source version 11.

Upgrade Module SDK in project settings to 11 or higher. Open project settings.

There are few scenarios which can cause the issue and we will discuss them in detail with solutions.

But before going into that, I believe its important to understand how Java compiler handles versions.

If you want to move on directly to the solution, please feel free to do so.

How Java compiler handles versions

Java has several versions 7, 8, 11, 17, 23, etc., with each versions have some level of backward compatibility built.

There are two primary cases of backward compatibility.

  1. Source compatibility - Ability of newer version of compiler to compile an older version of code.
  2. Bytecode compatibility - Ability of newer JVM to run older version bytecode.

Occasionally there are some changes that would break this backward compatibility but for most standard use cases you can expect newer versions to run older versions fairly well.

Now, since a developer can code in one version, compile it in another and run in a totally different version causes compatibility issues which is the reason for this Release version X not supported error.

We can broadly classify these scenarios as below.

  • Application uses lower version (Ex: Java 8) features but compiles with a higher version JDK (Ex: Java 11)
  • Application uses higher version (Ex: Java 11) features but compiles with a lower version JDK (Ex: Java 8)
  • Application is developed and compiled with same version but ran in a different version JVM (Lower or Higher).

Java compiler javac provides some options like --source, --target, etc., to help manage these version differences.

An example command with these arguments is below.

javac --source 1.8 --target 11 App.java

Let's see each of them with some examples before going to the solutions.

--source

The --source is used to specify the Java version of your source code.

💡
The minimum --source version you can provide is the one that can support all the features you use in your code.

For example, if you use lambdas, they were introduced in Java 8, so that's the minimum version you can use.

You can pass any higher versions as long as they support your features (source backward compatibility).

Let's say we now need to use var keyword which is introduced in Java 11.

public static void main(String[] args) {
    var name = "Mike";
}

Now the minimum --source version supported by your project is Java 11.

If you pass a lower version like 1.8 for --source, you will get below error.

Command:

javac --source 1.8 --target 1.8 App.java

JDK 8 Output:

App.java:3: error: cannot find symbol
        var name = "Mike";
        ^
  symbol:   class var
  location: class App
1 error

JDK 11+ Output:

warning: [options] bootstrap class path not set in conjunction with -source 8
App.java:3: warning: as of release 10, 'var' is a restricted local variable type and cannot be used for type declarations or as the element type of an array
        var name = "Mike";
            ^
App.java:3: error: cannot find symbol
        var name = "Mike";
        ^
  symbol:   class var
  location: class App
1 error
2 warnings

We can ignore the difference in error messages, basically we will not be able to use a Java 11 feature in our code and build it with --source version less than 11, even if we compile it with a Java 11+ JDK.

--target

The --target is used to specify the minimum JVM version you wanna target.

💡
A valid value for --target can be anything between the --source value and JDK version you are using to build the program.

For example, if you have installed JDK 17 in your machine and running javac, and you are using 1.8 for --source, then the minimum possible value for --target will be 1.8 and the maximum possible will be 17.

If you try to use anything less than the --source version as below, you will get an error.

Command:

javac --source 1.8 --target 1.7 App.java

Output:

warning: source release 1.8 requires target release 8

If you try to use anything more that the JDK version as below, you will get an error as well. Note: I was using JDK 17 while running this, hence 19 is not supported.

Command:

javac --source 11 --target 19 App.java

Output:

error: invalid target release: 19
Usage: javac <options> <source files>
use --help for a list of possible options

To verify the bytecode version, one of the easiest way would be to open it in IntelliJ and it should show as below.

In this example, even though I used JDK 17 to compile it, since I passed --target 11, the compiled bytecode is of version 11.

If you try to run it in a lower version JDK like 1.8, you will get below error.

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: App has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:473)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:621)

If you try to run it in a higher version JDK like 17, it will work fine.

-bootclasspath

Remember in our --source example we tried to build a code that used the var keyword from Java 11 and tried to build it with --source 1.8? We got a cannot find symbol error.

But that won't be the case always while building a higher version feature using lower version.

If your code uses a newer feature that would make the syntax incompatible with older version like var keyword, then you will get cannot find symbol error.

If your code uses a newly added method for example String.isBlank() added in Java 11, it won't cause error while compiling with lower version but would throw error during runtime.

Example:

public static void main(String[] args) {
    String name = "Mike";
    System.out.println(name.isBlank());
}

That's because new methods added are annotated with @since comments, but Java compiler does not consider it.

So if you try to build above code with javac --source 1.8 --target 1.8 App.java it will compile without any errors. But if you try to run it with JRE 8, you will get below error.

Exception in thread "main" java.lang.NoSuchMethodError: java.lang.String.isBlank()Z
        at App.main(App.java:4)

To capture such issues during compile time itself, we have to pass JDK 8 path while compiling using -bootclasspath argument as below.

javac --source 1.8 --target 1.8 -bootclasspath C:\Users\ErrorBuddy\.jdks\corretto-1.8.0_422\jre\lib\rt.jar App.java 

And now we get proper error which helps us know we are building with wrong version.

App.java:4: error: cannot find symbol
        System.out.println(name.isBlank());
                               ^
  symbol:   method isBlank()
  location: variable name of type String
1 error

--release

Naturally we would think its too much things to do for simply trying to compile for a different version.

Good thing, Java folks though so as well. That's why they added the shortcut --release since Java 9.

💡
When you specify --release you don't need to specify any of the others like --source, --target or -bootclasspath.

You can specify it as below.

Command:

javac --release 9 App.java 

Output:

App.java:4: error: cannot find symbol
        System.out.println(name.isBlank());
                               ^
  symbol:   method isBlank()
  location: variable name of type String
1 error

Note: Since it is introduced only in Java 9, it will not support running lower versions like 1.8 and will give below error.

error: release version 1.8 not supported
Usage: javac <options> <source files>
use --help for a list of possible options

Now that we seen how different version configurations can cause release version X not supported error, let's look at the solutions.

Common Solutions

1. Maven project version configurations

If you are not using maven, please feel free to skip to the next section.

Maven compiles an application using maven-compiler-plugin and uses below default configuration in pom.xml to identify expected Java version.

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

This has pretty much every issue we talked about in our previous section.

For example, let's consider in our code we used String.isBlank() which is a Java 11 feature but in our pom.xml, we have configured version as 1.8.

public static void main(String[] args) {
    String name = "Mark";
    System.out.println(name.isBlank());
}

As long as you do the maven build with a JDK version of 11+, it will build successfully. Because as we discussed in previous section, without -bootclasspath, Java compiler does not know if the features used are supported for the source and target version.

But if you try to run the maven project as below, you will get an error.

Command:

java -cp .\target\version-test-1.0-SNAPSHOT.jar App

Output:

Exception in thread "main" java.lang.NoSuchMethodError: java.lang.String.isBlank()Z
        at App.main(App.java:4)

To resolve that, you either have to change the maven.compiler.source and maven.compiler.target properties in pom.xml to 11.

Or if your JDK is 9+, and you maven version is 3.9.0+, you can simply specify maven.compiler.release as below.

<properties>
    <maven.compiler.release>11</maven.compiler.release>
</properties>

What if I am using an older version of maven?

If you are using a maven version less than 3.9.0, it ships with an older maven-compiler-plugin that does not support maven.compiler.release property.

So you can add the below <plugin> section to have the same functionality.

<?xml version="1.0" encoding="UTF-8"?>
<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>org.example</groupId>
    <artifactId>version-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <release>11</release>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2. IntelliJ Java version configurations

If you are building or running a project in IntelliJ and facing this issue, you have to make sure that IntelliJ is configured to use the correct version of Java you intent to use.

There are quite a few places you need to check. We'll list them all below.

File -> Project structure -> Project Settings -> Project -> SDK & Language Level

File -> Project structure -> Project Settings -> Modules -> Sources -> Language Level (Repeat for each modules)

File -> Settings -> Build, Execution, Deployment -> Compiler -> Java Compiler -> Project bytecode version

File -> Settings -> Build, Execution, Deployment -> Compiler -> Java Compiler -> Module -> Target bytecode version (Repeat for each modules)

2. Command-line Java version configurations

While building or running Java projects in command line, you can check whether you are using the appropriate java version by using java -version command, which should give similar output as below.

openjdk version "11.0.24" 2024-07-16 LTS
OpenJDK Runtime Environment Corretto-11.0.24.8.1 (build 11.0.24+8-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.24.8.1 (build 11.0.24+8-LTS, mixed mode)

If not, please install/configure the appropriate version.

For example, in windows, you can add a JAVA_HOME environmental variable with the installation path of your JDK as value.

Also add %JAVA_HOME%/bin to your Path environmental variable.

Conclusion

Whew, that's a length guide. I hope it helped you understand how versioning works in Java and how you can effectively resolve Release version not supported errors.

Happy coding!