I developed and built my Java application using Maven. I need to support Java 1.6, so I use the following properties:
<maven.compiler.target>1.6</maven.compiler.target> <maven.compiler.source>1.6</maven.compiler.source>
Still, when I run the application I get an "Unsupported major.minor version" error and I suspect that one of my dependency jars is compiled with a Java version newer than the one I need to support.
My questions:
Is this even possible? I thought Maven would take care of this kind of dependency version problems.
Is there an easy way to find out the minor/major version of all my dependencies? (Would be awesome if it could be shown when doing mvn dependency:tree
for instance.)
1 for LTS) requires Java 8 thus Maven jobs must be launched with a JDK >= 8.
Additionally, starting from Spring Boot 2.0, Java 8 is the minimum version.
In case of Maven, we specify the compiler plugin to use Maven with Java 17. The next step is to basically upgrade the dependencies of our application. We can do that, already, on the current version of Java which we're using, and simply upgrade all the dependencies, check if the application still works.
Chances are that it just runs fine with Java 11. Hint: You can speed up multi-module Maven projects by using parallel builds, e.g. mvn -T 4 compile compiles all modules in parallel on 4 CPU cores.
The problem is that every dependency (maintainer) can decide on it's own which java version is used to compile (1.5, 1.6, 1.7, 1.8 etc) so this is not solvable via Maven. But you can make sure that you don't use dependencies which are using a different Java version than you like to have.
This can be enfored by using Maven Enforcer Plugin by using extra-enforcer-rules:
<project> [...] <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.4.1</version> <!-- find the latest version at http://maven.apache.org/plugins/maven-enforcer-plugin/ --> <executions> <execution> <id>enforce-bytecode-version</id> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <enforceBytecodeVersion> <maxJdkVersion>1.6</maxJdkVersion> <excludes> <exclude>org.mindrot:jbcrypt</exclude> </excludes> </enforceBytecodeVersion> </rules> <fail>true</fail> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.codehaus.mojo</groupId> <artifactId>extra-enforcer-rules</artifactId> <version>1.0-beta-5</version> </dependency> </dependencies> </plugin> </plugins> </build> [...] </project>
This will break your build if you have a dependency which is compiled with a different version of JDK than you want to have.
To answer your two questions:
Yes, this is possible. Looking at the docs
, the <maven.compiler.target>
and <maven.compiler.source>
properties simply tells Maven which version of javac
to use to compile your project. And I quote, for your reference:
Note: Merely setting the target option does not guarantee that your code actually runs on a JRE with the specified version. The pitfall is unintended usage of APIs that only exist in later JREs which would make your code fail at runtime with a linkage error. To avoid this issue, you can either configure the compiler's boot classpath to match the target JRE or use the Animal Sniffer Maven Plugin to verify your code doesn't use unintended APIs.
The magic number after the Unsupported major.minor version
error actually tells the version of the JRE the class file is compatible with:
J2SE 8 = 52, J2SE 7 = 51, J2SE 6.0 = 50, J2SE 5.0 = 49, JDK 1.4 = 48, JDK 1.3 = 47, JDK 1.2 = 46, JDK 1.1 = 45
I don't know if there is an easy way to tell the major/minor version of ALL the dependencies (and transitive dependencies) in a project though.
UPDATE: Though I haven't used it before, I wonder the Animal Sniffer Maven plugin will help to sniff out the major/minor version of your dependencies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With