Сборка Maven, как использовать rt.jar, который в версии Java 1.6 или ранее
У меня есть устаревший источник, который использует 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 ответа
Вы сталкиваетесь с распространенным неправильным пониманием кросс-компиляции Java в специальном случае: вы хотите использовать sun.*
классы, которые не гарантируют совместимость между версиями Java. Из официальной записки Oracle
Java-программа, которая напрямую вызывает
sun.*
пакеты не гарантированно работают на всех Java-совместимых платформах. На самом деле, такая программа не гарантирует работу даже в будущих версиях на той же платформе.
В вашем конкретном случае настройка source
/ target
Плагин Maven Compiler не будет достаточно. И вообще действительно опасно. Компилятор Java знает только о байт-коде, а не о Java API (rt.jar
файл). Таким образом, компиляция с использованием компилятора Java 7 будет по-прежнему использовать rt.jar
Java 7, который в вашем случае будет нарушать код для Java 6 (особенно из-за sun.*
использование).
Проверьте этот SO ответ для более глубокого объяснения по этому вопросу. Проверьте также комментарии Стюарта Маркс из Oracle, если у вас есть сомнения по поводу его содержания.
В вашем конкретном случае вы, следовательно, обязательно должны установить JDK 6, потому что вам нужно указать на JDK 6 rt.jar
файл для API Java 6, иначе ваш код никогда не будет компилироваться правильно. Для таких вы можете использовать executable
Опция Maven Compiler Plugin, чтобы указать на другую установку JDK для использования в сочетании с fork
вариант.
Тем не менее, вы должны сделать то же самое для выполнения теста, а также в целом для любого плагина, требующего этот переключатель. Следовательно, более надежным подходом было бы установить JAVA_HOME
переменная заранее перед каждой сборкой (чтобы указать на JDK 6) или использовать набор инструментов Maven и установить JDK для использования в наборе плагинов Maven. Но, опять же, вам нужен JDK 6, установленный в вашей системе, иначе он не будет работать.
Вы также можете рассмотреть профили Maven, чтобы изолировать различное использование JDK. В таком профиле я бы также предложил добавить плагин Animal Sniffer Maven, как описано в вышеупомянутом ответе SO.
В качестве общих соображений, приведенные выше пункты объясняют, почему и как вы могли бы это временно исправить, но ваше приложение и сборка могут легко страдать от головной боли при обслуживании. Более структурированный подход определенно должен исправить использование sun.*
пакет, который действительно плохая практика. Но, тем не менее, даже в этом случае следует помнить о кросс-компиляции, это сложная тема, которую часто недооценивают.
Вы можете попробовать поиграть с этим:
<properties>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
Вы можете добавить плагин компилятора maven в файл pom.xml.
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>
Играйте с разными значениями источника и цели здесь. Вы должны получить это.