简体   繁体   English

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

[英]Maven build how to use rt.jar which in java version 1.6 or before

I have legacy source which uses new FtpClient() , and found that FtpClient is a abstract class in jre1.7. 我有遗留源使用new FtpClient() ,并发现FtpClient是jre1.7中的抽象类。 The code is fine for jre1.6 or before. 该代码适用于jre1.6或之前。

I am using maven to build my project now. 我正在使用maven来构建我的项目。 My JAVA_HOME points to jdk1.7, which cause the compilation of my source failure. 我的JAVA_HOME指向jdk1.7,导致编译我的源代码失败。 But it is fine when my JAVA_HOME point to jdk1.6. 但是当我的JAVA_HOME指向jdk1.6时它很好。 However, the jdk versioin in my company is 1.7 default, and would not downgrade to version 1.6. 但是,我公司的jdk versioin默认为1.7,并且不会降级到1.6版本。

Question : how to make it work to compile my source without change the JAVA_HOME ? 问题 :如何在不更改JAVA_HOME情况下编译我的源代码?

Below the concerned build log: 在相关的构建日志下面:

[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

you can try to play with that: 你可以试着玩这个:

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

You can add the maven compiler plugin in the pom.xml file. 您可以在pom.xml文件中添加maven编译器插件。

https://maven.apache.org/plugins/maven-compiler-plugin/ 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>

Play with different values of source and target here. 在这里玩不同的源和目标值。 You should get it. 你应该得到它。

You are hitting a common misunderstanding of Java cross-compilation with a special case: you want to use sun.* classes, which have no guarantee to be compatible across Java versions. 您在使用特殊情况时遇到了对Java交叉编译的常见误解:您希望使用sun.*类,这些类无法保证在Java版本之间兼容。 From official Oracle note 来自官方的Oracle笔记

A Java program that directly calls into sun.* packages is not guaranteed to work on all Java-compatible platforms. 直接调用sun.*包的Java程序不能保证在所有兼容Java的平台上运行。 In fact, such a program is not guaranteed to work even in future versions on the same platform. 实际上,即使在同一平台上的未来版本中,也不能保证这样的程序能够工作。

In your specific case, setting source / target of the Maven Compiler Plugin would not be enough. 在您的特定情况下,设置Maven编译器插件的source / target是不够的。 And in general is really dangerous. 一般来说真的很危险。 The Java compiler only knows about bytecode, not about Java API (the rt.jar file). Java编译器只知道字节码,而不是Java API( rt.jar文件)。 So compiling using Java 7 compiler would still use the rt.jar of Java 7, which in your case is going to break code for Java 6 (especially because of the sun.* usage). 因此,使用Java 7编译器编译仍然会使用Java 7的rt.jar ,在您的情况下,它将破坏Java 6的代码(特别是因为sun.*用法)。

Check this SO answer for a more in deep explanation on the matter. 请查看此SO答案 ,以获得有关此事的更深入解释。 Check also comments from Stuart Marks from Oracle, if ever you have doubts about its content. 如果您对其内容有疑问,请查看Oracle的Stuart Marks的评论。


In your specific case, you hence mandatory need a JDK 6 installed, because you need to point to the JDK 6 rt.jar file for Java 6 API, otherwise your code would never compile correctly. 在您的特定情况下,您因此必须安装JDK 6,因为您需要指向Java 6 API的JDK 6 rt.jar文件,否则您的代码将永远无法正确编译。 For such, you could use the executable option of the Maven Compiler Plugin, to point at a different installation of JDK to use, in conjunction with the fork option. 为此,您可以使用Maven编译器插件的executable选项,指向要使用的不同JDK安装,以及fork选项。

However, you would have to do the same for test execution as well and in general for any plugin requiring this switch. 但是,对于任何需要此切换的插件,您也必须对测试执行执行相同的操作。 Hence, a more reliable approach would be to set the JAVA_HOME variable upfront before every build (to point to JDK 6) or to use Maven toolchain and set a JDK to use across a set of Maven plugins. 因此,更可靠的方法是在每次构建之前预先设置JAVA_HOME变量(指向JDK 6)或使用Maven工具链并设置JDK以在一组Maven插件中使用。 But, again, you need JDK 6 installed in your system, otherwise it would not work. 但是,同样,您需要在系统中安装JDK 6,否则它将无法工作。

You may also consider Maven profiles to isolate the different JDK usage. 您还可以考虑使用Maven配置文件来隔离不同的JDK用法。 In such a profile, I would also suggest to add the Animal Sniffer Maven Plugin as described in the aforementioned SO answer. 在这样的配置文件中,我还建议添加动物嗅探器Maven插件 ,如上述SO答案中所述。


As general consideration, the points above explain the why and how you could fix it temporarily, but your application and build may easily suffer maintenance headaches. 作为一般考虑,上面的要点解释了为什么以及如何暂时解决它,但您的应用程序和构建可能很容易遇到维护问题。 A more structured approach is definitely to fix the usage of sun.* package, which is a really bad practice . 一个更有条理的方法肯定是修复sun.*包的使用,这是一个非常糟糕的做法 But, yet again, even then be aware about cross-compilation, it's a tricky topic which is often underestimated. 但是,再一次,即使在那时也要注意交叉编译,这是一个经常被低估的棘手话题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM