Maven构建如何使用java版本1.6或之前的rt.jar

时间:2016-03-24 06:07:53

标签: java maven maven-compiler-plugin

我有遗留源使用new FtpClient(),并发现FtpClient是jre1.7中的抽象类。该代码适用于jre1.6或之前。

我正在使用maven来构建我的项目。我的JAVA_HOME指向jdk1.7,导致编译我的源故障。但是当JAVA_HOME指向jdk1.6时,它很好。但是,我公司的jdk versioin默认为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

3 个答案:

答案 0 :(得分:1)

你可以尝试使用它:

<properties>
    <maven.compiler.source>1.6</maven.compiler.source>
    <maven.compiler.target>1.6</maven.compiler.target>
</properties>

答案 1 :(得分:0)

您可以在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>

在此处使用不同的源和目标值。你应该得到它。

答案 2 :(得分:0)

您在使用特殊情况时遇到了对Java交叉编译的常见误解:您希望使用sun.*类,这些类无法保证在Java版本之间兼容。来自official Oracle note

  

不能保证直接调用sun.*包的Java程序可以在所有兼容Java的平台上运行。实际上,即使在同一平台上的未来版本中,也不能保证这样的程序能够正常工作。

在您的特定情况下,设置Maven编译器插件的source / target是不够的。一般来说真的很危险。 Java编译器只知道字节码,而不是Java API(rt.jar文件)。因此,使用Java 7编译器进行编译仍将使用Java 7的rt.jar,在您的情况下,它将破坏Java 6的代码(特别是因为sun.*用法)。

检查this SO answer以获得有关此事的更深入解释。如果您对其内容有疑问,请查看Oracle的Stuart Marks的评论。

在您的特定情况下,因此强制需要安装JDK 6,因为您需要指向Java 6 API的JDK 6 rt.jar文件,否则您的代码永远不会编译正确。为此,您可以使用Maven编译器插件的executable选项指向要使用的不同JDK安装,并结合fork选项。

但是,对于任何需要此切换的插件,您也必须对测试执行执行相同的操作。因此,更可靠的方法是在每次构建之前预先设置JAVA_HOME变量(指向JDK 6)或使用Maven toolchain并设置JDK以在一组Maven插件中使用。但是,同样,您需要在系统中安装JDK 6,否则它将无法工作。

您也可以考虑Maven profiles来隔离不同的JDK用法。在这样的配置文件中,我还建议添加Animal Sniffer Maven Plugin,如前面提到的SO答案中所述。

作为一般考虑,上述几点解释了为什么以及如何临时修复它,但您的应用程序和构建可能很容易遭受维护问题。更结构化的方法肯定是要修复sun.*包的使用,即a really bad practice。但是,再一次,即使在那时也要注意交叉编译,这是一个经常被低估的棘手话题。