【问题标题】:Maven build how to use rt.jar which in java version 1.6 or beforeMaven构建如何使用java 1.6或之前版本的rt.jar
【发布时间】:2016-07-11 16:33:43
【问题描述】:

我有使用new FtpClient() 的遗留源,发现FtpClient 是jre1.7 中的一个抽象类。该代码适用于 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

【问题讨论】:

  • error: FtpClient is abstract; cannot be instantiated 代码错误,这不是 maven 配置或 java 语言版本问题
  • 修复代码或使用 Java 1.6。一开始就不应该使用sun.* 类。
  • @Evgeny Lebedev,但是我用jdk1.6编译时没有错误。

标签: java maven maven-compiler-plugin


【解决方案1】:

你可以试试看:

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

【讨论】:

  • @你的系统中有 jdk 1.6 吗?
  • @Bhavesh,是的,我有。但请注意,我不希望将 JAVA_HOME 设置为那个。
  • 这行不通,除非他同时使用 1.6 JDK 编译和执行。
  • 您是否尝试过编辑 mvn.bat?您可以覆盖该文件中的 JAVA_HOME 变量
  • 这个解决方案不起作用,检查我的答案,在这种情况下交叉编译真的很危险,而且几乎不可能因为 sun.* 包的使用。
【解决方案2】:

您在一个特殊情况下遇到了对 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 的 cmets。


在您的特定情况下,您因此强制需要安装 JDK 6,因为您需要指向 Java 6 API 的 JDK 6 rt.jar 文件,否则您的代码将永远无法正确编译。为此,您可以使用 Maven Compiler Plugin 的 executable 选项,与 fork 选项一起使用,以指向要使用的不同 JDK 安装。

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

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


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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 不工作... javac:源版本 1.7 需要目标版本 1.7
    猜你喜欢
    • 1970-01-01
    • 2020-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多