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.
- Source compatibility - Ability of newer version of compiler to compile an older version of code.
- 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.
--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.
--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
.
--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!