Maven build how to use rt.jar which in java version 1.6 or before
Maven build how to use rt.jar which in java version 1.6 or before
我有使用 new FtpClient()
的遗留源代码,发现 FtpClient
是 jre1.7 中的抽象 class。该代码适用于 jre1.6 或之前的版本。
我现在正在使用 maven 来构建我的项目。我的JAVA_HOME
指向jdk1.7,导致我源码编译失败。但是当我的 JAVA_HOME
指向 jdk1.6 时就可以了。但是,我公司的jdk版本默认是1.7,不会降级到1.6版本。
问题:如何在不更改 JAVA_HOME
的情况下编译我的源代码?
相关构建日志下方:
[INFO] Compiling 601 source files to C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\target\classes
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Compilation failure
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:[44,9] error: FtpClient is abstract; cannot be instantiated
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:[45,6] error: cannot find symbol
could not parse error message: symbol: method openServer(String)
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:46: error: no suitable method found for login(String,String)
aftp.login(user,psw);
^
could not parse error message: method FtpClient.login(String,char[],String) is not applicable
(actual and formal argument lists differ in length)
method FtpClient.login(String,char[]) is not applicable
(actual argument String cannot be converted to char[] by method invocation conversion)
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:47: error: cannot find symbol
aftp.ascii();
^
could not parse error message: symbol: method ascii()
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:53: error: FtpClient is abstract; cannot be instantiated
aftp = new FtpClient();
^
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:[54,6] error: cannot find symbol
could not parse error message: symbol: method openServer(String,int)
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:55: error: no suitable method found for login(String,String)
aftp.login(user,psw);
^
could not parse error message: method FtpClient.login(String,char[],String) is not applicable
(actual and formal argument lists differ in length)
method FtpClient.login(String,char[]) is not applicable
(actual argument String cannot be converted to char[] by method invocation conversion)
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:56: error: cannot find symbol
aftp.binary();
^
could not parse error message: symbol: method binary()
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:62: error: cannot find symbol
aftp.closeServer();
^
could not parse error message: symbol: method closeServer()
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:127: error: cannot find symbol
aftp.cd(RWFileDir);
^
could not parse error message: symbol: method cd(String)
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:128: error: cannot find symbol
TelnetOutputStream outs = aftp.put(filename);
^
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8 seconds
[INFO] Finished at: Thu Mar 24 14:12:52 CST 2016
你可以试试看:
<properties>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
可以在pom.xml文件中添加maven编译插件
https://maven.apache.org/plugins/maven-compiler-plugin/
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
在这里使用不同的源和目标值。你应该得到它。
你遇到了一个常见的误解 Java 交叉编译的特殊情况:你想使用 sun.*
类,它不能保证在 [=] 之间兼容47=] 版本。来自 official Oracle note
A Java program that directly calls into sun.*
packages is not guaranteed to work on all Java-compatible platforms. In fact, such a program is not guaranteed to work even in future versions on the same platform.
在您的特定情况下,设置 Maven 编译器插件的 source
/target
是不够的。总的来说真的很危险。 Java 编译器只知道字节码,不知道 Java API(rt.jar
文件)。所以使用 Java 7 编译器编译仍然会使用 Java 7 的 rt.jar
,在你的情况下这会破坏 Java 6 的代码(特别是因为 sun.*
用法)。
检查 以获得对此事的更深入的解释。如果您对其内容有任何疑问,还可以查看来自 Oracle 的 Stuart Marks 的评论。
在您的特定情况下,您因此 mandatory 需要安装 JDK 6,因为您需要指向 JDK 6 rt.jar
文件 Java 6 API,否则你的代码将永远无法正确编译。为此,您可以使用 executable
option of the Maven Compiler Plugin, to point at a different installation of JDK to use, in conjunction with the fork
选项。
但是,对于测试执行以及通常需要此开关的任何插件,您都必须执行相同的操作。因此,更可靠的方法是在每次构建之前预先设置 JAVA_HOME
变量(指向 JDK 6)或使用 Maven toolchain 并设置 JDK 以使用跨一组 Maven 插件。但是,同样,您需要在您的系统中安装 JDK 6,否则它将无法运行。
您也可以考虑 Maven profiles to isolate the different JDK usage. In such a profile, I would also suggest to add the Animal Sniffer Maven Plugin,如上述 SO 答案中所述。
作为一般考虑,以上几点解释了您可以临时修复它的原因和方法,但您的应用程序和构建可能很容易遇到维护问题。更结构化的方法肯定是修复 sun.*
包的用法,即 a really bad practice。但是,再说一遍,即使那样,也要注意交叉编译,这是一个经常被低估的棘手话题。
我有使用 new FtpClient()
的遗留源代码,发现 FtpClient
是 jre1.7 中的抽象 class。该代码适用于 jre1.6 或之前的版本。
我现在正在使用 maven 来构建我的项目。我的JAVA_HOME
指向jdk1.7,导致我源码编译失败。但是当我的 JAVA_HOME
指向 jdk1.6 时就可以了。但是,我公司的jdk版本默认是1.7,不会降级到1.6版本。
问题:如何在不更改 JAVA_HOME
的情况下编译我的源代码?
相关构建日志下方:
[INFO] Compiling 601 source files to C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\target\classes
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Compilation failure
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:[44,9] error: FtpClient is abstract; cannot be instantiated
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:[45,6] error: cannot find symbol
could not parse error message: symbol: method openServer(String)
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:46: error: no suitable method found for login(String,String)
aftp.login(user,psw);
^
could not parse error message: method FtpClient.login(String,char[],String) is not applicable
(actual and formal argument lists differ in length)
method FtpClient.login(String,char[]) is not applicable
(actual argument String cannot be converted to char[] by method invocation conversion)
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:47: error: cannot find symbol
aftp.ascii();
^
could not parse error message: symbol: method ascii()
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:53: error: FtpClient is abstract; cannot be instantiated
aftp = new FtpClient();
^
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:[54,6] error: cannot find symbol
could not parse error message: symbol: method openServer(String,int)
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:55: error: no suitable method found for login(String,String)
aftp.login(user,psw);
^
could not parse error message: method FtpClient.login(String,char[],String) is not applicable
(actual and formal argument lists differ in length)
method FtpClient.login(String,char[]) is not applicable
(actual argument String cannot be converted to char[] by method invocation conversion)
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:56: error: cannot find symbol
aftp.binary();
^
could not parse error message: symbol: method binary()
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:62: error: cannot find symbol
aftp.closeServer();
^
could not parse error message: symbol: method closeServer()
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:127: error: cannot find symbol
aftp.cd(RWFileDir);
^
could not parse error message: symbol: method cd(String)
location: variable aftp of type FtpClient
C:\MyData\Project\A-Trunk\CCA\Online\branches\CCA_TabletAccess_Maven\Common_Source\src\com\hhbb\cca\services\ens\util\FTPCommon.java:128: error: cannot find symbol
TelnetOutputStream outs = aftp.put(filename);
^
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8 seconds
[INFO] Finished at: Thu Mar 24 14:12:52 CST 2016
你可以试试看:
<properties>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
可以在pom.xml文件中添加maven编译插件
https://maven.apache.org/plugins/maven-compiler-plugin/
<project>
[...]
<build>
[...]
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
[...]
</build>
[...]
</project>
在这里使用不同的源和目标值。你应该得到它。
你遇到了一个常见的误解 Java 交叉编译的特殊情况:你想使用 sun.*
类,它不能保证在 [=] 之间兼容47=] 版本。来自 official Oracle note
A Java program that directly calls into
sun.*
packages is not guaranteed to work on all Java-compatible platforms. In fact, such a program is not guaranteed to work even in future versions on the same platform.
在您的特定情况下,设置 Maven 编译器插件的 source
/target
是不够的。总的来说真的很危险。 Java 编译器只知道字节码,不知道 Java API(rt.jar
文件)。所以使用 Java 7 编译器编译仍然会使用 Java 7 的 rt.jar
,在你的情况下这会破坏 Java 6 的代码(特别是因为 sun.*
用法)。
检查
在您的特定情况下,您因此 mandatory 需要安装 JDK 6,因为您需要指向 JDK 6 rt.jar
文件 Java 6 API,否则你的代码将永远无法正确编译。为此,您可以使用 executable
option of the Maven Compiler Plugin, to point at a different installation of JDK to use, in conjunction with the fork
选项。
但是,对于测试执行以及通常需要此开关的任何插件,您都必须执行相同的操作。因此,更可靠的方法是在每次构建之前预先设置 JAVA_HOME
变量(指向 JDK 6)或使用 Maven toolchain 并设置 JDK 以使用跨一组 Maven 插件。但是,同样,您需要在您的系统中安装 JDK 6,否则它将无法运行。
您也可以考虑 Maven profiles to isolate the different JDK usage. In such a profile, I would also suggest to add the Animal Sniffer Maven Plugin,如上述 SO 答案中所述。
作为一般考虑,以上几点解释了您可以临时修复它的原因和方法,但您的应用程序和构建可能很容易遇到维护问题。更结构化的方法肯定是修复 sun.*
包的用法,即 a really bad practice。但是,再说一遍,即使那样,也要注意交叉编译,这是一个经常被低估的棘手话题。