我已经尝试了一段时间,但还没有成功。
我想运行指向JDK7的JAVA_HOME
,但我想为JVM 5编译一个项目。我仔细阅读了文档,在SO上发现了类似的帖子,但似乎没有一个在我的设置中起作用。
我第一次尝试只设置target
和source
,但我得到了一个错误:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
[ClassName]
不是抽象的,并且不覆盖CommonDataSource
中的抽象方法getParentLogger()
据我所知,这个类是在JDK7中更新的,只是添加了引发错误的额外方法。我需要使用JDK5的运行时,它有旧的实现,一切都应该正常工作。所以我这样做:
<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>
我的系统上正确设置了JAVA5_HOME,我可以看到它在日志中加载了正确的类,但我遇到了另一个错误:
[loading ZipFileIndexFileObject[c:Program FilesJavajdk1.5.0_22jrelibrt.jar(*.class)]]
…
…[ClassName]
错误:包javax.crypto
不存在
这很公平,因为我没有在bootclasspath
中包含jce.jar
(密码学类)。不过,有一件事让我感到困惑。尽管bootclasspath
只包含Java 5运行时,但我在类路径中有很多来自JRE7的库。它们在任何地方都没有指定。
[类文件的搜索路径:c:\Program files(x86)\Java\jdk1.5.0_22\jre\lib\rt.jar,c:\ProgramFiles\Java\jdk1.7.0_02\jre\lib\ext\dnsns.jar,c:\ProgramFiles\Java\jdk1.7.0_02\jre\lib\ext\localedata.jar,c:\ProgramFiles\Java\jdk1.7.0_02\jre\lib\ext\sunec.jar,c:\ProgramFiles\Java\jdk1.7.0_02\jre\lib\ext\sunjce_provider.jar,c:\ProgramFiles\Java\jdk1.7.0_02\jre\lib\ext\sunmscapi.jar,c:\ProgramFiles\Java\jdk1.7.0_02\jre\lib\ext\zipfs.jar,…]
如果我尝试添加jce.jar(来自JRE5),我会返回到第一个错误:
<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>
类型[ClassName]必须实现继承的抽象方法CommonDataSource.getParentLogger()
我也没有看到rt.jar
被加载的痕迹,但我没有得到java.lang
未找到的错误,所以在类路径上加载了一些类。
我将通过制作一个批处理脚本来临时修复它,该脚本在构建之前覆盖JAVA_HOME
,然后再将其设置回原处,但我真的希望以正确的方式完成这项工作。这似乎不是一个极端的用例。:)
我在这里做错了什么?
这个答案是针对问题的标题,而不是针对问题的具体问题进行详细回答
我最终在我的项目中使用了这个解决方案,它允许我通过激活maven概要文件来选择性地使用自定义引导类路径。我强烈建议为此使用概要文件,因为否则,对于任何没有环境变量集的人来说,构建都会失败(非常糟糕,尤其是对于开源项目)。我只在IDE中激活此配置文件以执行"清理和构建"操作。
<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>
早期版本的Java我们并不特别擅长支持早期版本的Java。对于Java7来说,它似乎要好得多。
这是一个可以在任何版本下编译的程序。
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
如果您需要为以前版本的Java进行编译,则需要提供一个bootclasspath,非常适合您想要编译的Java版本。Java 7似乎能够一直支持Java 1.2
如果需要,可以在maven编译器插件上使用bootclasspath配置选项:
<compilerArguments>
<bootclasspath>xxxxxxxxx</bootclasspath>
</compilerArguments>
你可以在这里阅读更多关于它的信息。请参阅示例下的注释。
问题在于Java 7的向后兼容性。
由于无法解决不同性质的问题,很少有类不能保持向后兼容性,DataSource恰好就是其中之一。
因此,要么调整类以尊重新的签名(即使在向后兼容模式下),要么将被迫使用不同版本的虚拟机。
您可以在此处阅读更多信息:http://www.oracle.com/technetwork/java/javase/compatibility-417013.html
要在Maven编译器选项中使用多个jar,请在jar之间使用${path.separator}字符串:
<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>