问题
I've been trying to get this to work for a while now but no luck yet.
I want to run with JAVA_HOME
pointing to JDK7 but I want to compile a project for JVM 5. I've read through documentation, I've found similar posts on SO, but none of them seem to work in my setup.
I first tried with setting just target
and source
but I got an error:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
[ClassName]
is not abstract and does not override abstract methodgetParentLogger()
inCommonDataSource
As far as I understood that class was updated in JDK 7 and the extra method that's throwing the error was just added. I need to use the runtime of JDK 5 that has the old implementation and everything should work fine. So I do this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<verbose>true</verbose>
<source>1.5</source>
<target>1.5</target>
<compilerArguments>
<bootclasspath>${env.JAVA5_HOME}/jre/lib/rt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
I have JAVA5_HOME set correctly on my system, I can see it loading the correct classes in the log, but I hit another error:
[loading ZipFileIndexFileObject[c:\Program Files\Java\jdk1.5.0_22\jre\lib\rt.jar(*.class)]]
...
...[ClassName]
error: packagejavax.crypto
does not exist
Which is fair enough, since I didn't include jce.jar
(cryptography classes) in the bootclasspath
. There is a thing that puzzles me, though. Even though the bootclasspath
contains only the Java 5 runtime, I have a lot of libraries from JRE7 in the classpath. They are not specified anywhere.
[search path for class files: c:\Program Files (x86)\Java\jdk1.5.0_22\jre\lib\rt.jar,c:\Program Files\Java\jdk1.7.0_02\jre\lib\ext\dnsns.jar,c:\Program Files\Java\jdk1.7.0_02\jre\lib\ext\localedata.jar,c:\Program Files\Java\jdk1.7.0_02\jre\lib\ext\sunec.jar,c:\Program Files\Java\jdk1.7.0_02\jre\lib\ext\sunjce_provider.jar,c:\Program Files\Java\jdk1.7.0_02\jre\lib\ext\sunmscapi.jar,c:\Program Files\Java\jdk1.7.0_02\jre\lib\ext\zipfs.jar, ...]
If I try and add jce.jar (from JRE5), I get back to the first error:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<verbose>true</verbose>
<source>1.5</source>
<target>1.5</target>
<compilerArguments>
<bootclasspath>${env.JAVA5_HOME}/jre/lib/rt.jar${path.separator}${env.JAVA5_HOME}/jre/lib/jce.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
The type [ClassName] must implement the inherited abstract method CommonDataSource.getParentLogger()
I also see no trace of rt.jar
being loaded, but I don't get a java.lang
not found error, so there are some classes being loaded on the classpath.
I'll fix it temporarily by making a batch script that overwrites JAVA_HOME
before building and sets it back afterwards, but I really want this done the right way. This doesn't seem as such an extreme use-case. :)
What am I doing wrong here?
回答1:
This answer is targeted at the title of the question, not to the specific problems of the question in detail.
I ended up using this solution in my project, which allows me to use the custom bootstrap classpath selectively, by activating a maven profile. I strongly recommend using a profile for this, because otherwise it makes the build fail for anyone that does not have the environment variable set (very bad, especially for an open source project). I only activate this profile in my IDE for the "Clean & Build" action.
<profile>
<id>compileWithJava5</id>
<!--
NOTE
Make sure to set the environment variable JAVA5_HOME
to your JDK 1.5 HOME when using this profile.
-->
<properties>
<java.5.home>${env.JAVA5_HOME}</java.5.home>
<java.5.libs>${java.5.home}/jre/lib</java.5.libs>
<java.5.bootclasspath>${java.5.libs}/rt.jar${path.separator}${java.5.libs}/jce.jar</java.5.bootclasspath>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<compilerArguments>
<bootclasspath>${java.5.bootclasspath}</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
回答2:
Previous version of Java we not particularly good at supporting previous versions of Java. For Java 7 it appears to be much better.
Here is a program which should compile under any version.
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
$ javac -target 1.7 -source 1.7 Main.java
$ javac -target 1.6 -source 1.6 Main.java
warning: [options] bootstrap class path not set in conjunction with -source 1.6
1 warning
$ javac -Xbootclasspath:/usr/java/jdk1.6.0_29/jre/lib/rt.jar -target 1.6 -source 1.6 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.5.0_22/jre/lib/rt.jar -target 1.5 -source 1.5 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.4.0_30/jre/lib/rt.jar -target 1.4 -source 1.4 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.3.1_29/jre/lib/rt.jar -target 1.3 -source 1.3 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.2.2_017/jre/lib/rt.jar -target 1.2 -source 1.2 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.1.8_16/jre/lib/rt.jar -target 1.1 -source 1.2 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.1.8_16/jre/lib/rt.jar -target 1.1 -source 1.1 Main.java
javac: invalid source release: 1.1
Usage: javac
use -help for a list of possible options
$ javac -Xbootclasspath:/usr/java/jdk1.1.8_16/jre/lib/rt.jar -target 1.0 -source 1.0 Main.java
javac: invalid target release: 1.0
Usage: javac
use -help for a list of possible options
If you need to compile for a previous version of Java, you need to provide a bootclasspath, ideally for the version of Java you want to compile for. Java 7 appears to be able to support all the way back to Java 1.2
回答3:
You can use the bootclasspath configuration option on the maven-compiler-plugin if needed:
<compilerArguments>
<bootclasspath>xxxxxxxxx</bootclasspath>
</compilerArguments>
You can read more about it here. See the note under the example.
回答4:
The problem is with Java 7 backwards compatibility.
There are very few classes that don't preserve backwards compatibility due to impossible to resolve issues of different nature, DataSource happens to be one of them.
So, either you adapt your class to respect the new signatures (even when in backwards compatibility mode), or you'll be forced to use a different version of the virtual machine.
You can read further information here: http://www.oracle.com/technetwork/java/javase/compatibility-417013.html
回答5:
To use multiple Jars in the Maven compiler options, use the ${path.separator} string between the jars:
<compilerArguments>
<bootclasspath>${env.JAVA5_HOME}/jre/lib/rt.jar${path.separator}${env.JAVA5_HOME}/jre/lib/jce.jar${path.separator}${env.JAVA5_HOME}/jre/lib/jsse.jar</bootclasspath>
</compilerArguments>
来源:https://stackoverflow.com/questions/9164625/maven-use-jdk-7-to-compile-for-jvm-5