Reputation: 421040
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.)
Upvotes: 32
Views: 21438
Reputation: 97437
The problem is that every dependency (maintainer) can decide on its 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.
Upvotes: 45
Reputation: 9268
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.
Upvotes: 2