Maven - используйте JDK 7 для компиляции для JVM 5

Я пытался заставить это работать какое-то время, но пока не повезло.

Я хочу запустить с JAVA_HOME, указывая на JDK7, но я хочу скомпилировать проект для JVM 5. Я прочитал documentation, Я нашел похожие сообщения на SO, но ни один из них, похоже, не работает в моей настройке.

Сначала я попытался установить только target и source, но я получил ошибку:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.5</source>
        <target>1.5</target>
    </configuration>
</plugin>

[ClassName] не является абстрактным и не отменяет абстрактного метода getParentLogger() в CommonDataSource

Насколько я понял, этот класс был обновлен в JDK 7, и добавлен дополнительный метод, который бросает ошибку. Мне нужно использовать среду выполнения JDK 5, которая имеет старую реализацию, и все должно работать нормально. Поэтому я делаю это:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <verbose>true</verbose>
        <source>1.5</source>
        <target>1.5</target>
        <compilerArguments>
            <bootclasspath>${env.JAVA5_HOME}/jre/lib/rt.jar</bootclasspath>
        </compilerArguments>
    </configuration>
</plugin>

У меня JAVA5_HOME правильно установлен в моей системе, я вижу, что он загружает правильные классы в журнал, но я ударил еще одну ошибку:

[loading ZipFileIndexFileObject[c:\Program Files\Java\jdk1.5.0_22\jre\lib\rt.jar(*.class)]]
...
...
[ClassName] Ошибка: пакет javax.crypto не существует

Это справедливо, так как я не включил jce.jar (классы криптографии) в bootclasspath. Тем не менее, есть что-то, что меня озадачивает. Несмотря на то, что bootclasspath содержит только среду исполнения Java 5, у меня есть много библиотек из JRE7 в пути к классам. Они нигде не указаны.

[путь поиска для файлов классов: c:\Program Files (X86)\Java\jdk1.5.0_22\JRE\Lib\rt.jar, C:\Program Files\Java\jdk1.7.0_02\JRE\Lib\вн\dnsns.jar, C:\Program Files\Java\jdk1.7.0_02\JRE\Lib\вн\localedata.jar, C:\Program Files\Java\jdk1.7.0_02\JRE\Lib\вн\sunec.jar, C:\Program Files\Java\jdk1.7.0_02\JRE\Lib\вн\sunjce_provider.jar, C:\Program Files\Java\jdk1.7.0_02\JRE\Lib\вн\sunmscapi.jar, C:\Program Файлы \Java\jdk1.7.0_02\jre\lib\ext\zipfs.jar,...]

Если я попытаюсь добавить jce.jar(из JRE5), я вернусь к первой ошибке:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <verbose>true</verbose>
        <source>1.5</source>
        <target>1.5</target>
        <compilerArguments>
            <bootclasspath>${env.JAVA5_HOME}/jre/lib/rt.jar${path.separator}${env.JAVA5_HOME}/jre/lib/jce.jar</bootclasspath>
        </compilerArguments>
    </configuration>
</plugin>

Тип [ClassName] должен реализовать унаследованный абстрактный метод CommonDataSource.getParentLogger()

Я также не вижу следов rt.jar, загружаемых, но я не получаю ошибку java.lang not found, поэтому в пути к классам загружаются некоторые классы.

Я исправлю это временно, сделав пакетный пакет script, который перезаписывает JAVA_HOME перед созданием и устанавливает его обратно, но я действительно хочу, чтобы это было правильно. Это не похоже на такой крайний случай использования.:)

Что я здесь делаю неправильно?

Ответ 1

Этот ответ нацелен на название вопроса, а не на конкретные проблемы вопроса в деталях.

В конечном итоге я использовал это решение в своем проекте, что позволяет выборочно использовать выборочный путь класса bootstrap, активируя профиль maven. Я настоятельно рекомендую использовать для этого профиль, потому что в противном случае это приведет к сбою сборки для любого, у кого нет установленной переменной окружения (очень плохо, особенно для проекта с открытым исходным кодом). Я активирую этот профиль только в своей среде IDE для действия "Очистить и построить".

    <profile>
        <id>compileWithJava5</id>
        <!--
            NOTE
            Make sure to set the environment variable JAVA5_HOME
            to your JDK 1.5 HOME when using this profile.
        -->
        <properties>
            <java.5.home>${env.JAVA5_HOME}</java.5.home>
            <java.5.libs>${java.5.home}/jre/lib</java.5.libs>
            <java.5.bootclasspath>${java.5.libs}/rt.jar${path.separator}${java.5.libs}/jce.jar</java.5.bootclasspath>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.5</source>
                        <target>1.5</target>
                        <compilerArguments>
                            <bootclasspath>${java.5.bootclasspath}</bootclasspath>
                        </compilerArguments>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>

Ответ 2

Предыдущая версия Java не особенно хороша в поддержке предыдущих версий Java. Для Java 7 это выглядит намного лучше.

Вот программа, которая должна компилироваться в любой версии.

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

$ javac -target 1.7 -source 1.7 Main.java
$ javac -target 1.6 -source 1.6 Main.java
warning: [options] bootstrap class path not set in conjunction with -source 1.6
1 warning
$ javac -Xbootclasspath:/usr/java/jdk1.6.0_29/jre/lib/rt.jar -target 1.6 -source 1.6 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.5.0_22/jre/lib/rt.jar -target 1.5 -source 1.5 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.4.0_30/jre/lib/rt.jar -target 1.4 -source 1.4 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.3.1_29/jre/lib/rt.jar -target 1.3 -source 1.3 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.2.2_017/jre/lib/rt.jar -target 1.2 -source 1.2 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.1.8_16/jre/lib/rt.jar -target 1.1 -source 1.2 Main.java
$ javac -Xbootclasspath:/usr/java/jdk1.1.8_16/jre/lib/rt.jar -target 1.1 -source 1.1 Main.java
javac: invalid source release: 1.1
Usage: javac  
use -help for a list of possible options
$ javac -Xbootclasspath:/usr/java/jdk1.1.8_16/jre/lib/rt.jar -target 1.0 -source 1.0 Main.java
javac: invalid target release: 1.0
Usage: javac  
use -help for a list of possible options

Если вам нужно скомпилировать предыдущую версию Java, вам необходимо предоставить bootclasspath, идеально подходящую для версии Java, для которой вы хотите скомпилировать. Кажется, что Java 7 поддерживает весь путь назад к Java 1.2

Ответ 3

При необходимости вы можете использовать опцию конфигурации bootclasspath в maven-compiler-plugin:

<compilerArguments>
    <bootclasspath>xxxxxxxxx</bootclasspath>
</compilerArguments>

Вы можете прочитать об этом здесь. См. Примечание в примере.

Ответ 4

Проблема заключается в совместимости с Java 7.

Существует очень мало классов, которые не сохраняют обратную совместимость из-за невозможности решения проблем различной природы, DataSource является одним из них.

Итак, либо вы адаптируете свой класс к соблюдению новых подписей (даже в режиме обратной совместимости), либо вы будете вынуждены использовать другую версию виртуальной машины.

Вы можете прочитать дополнительную информацию здесь: http://www.oracle.com/technetwork/java/javase/compatibility-417013.html

Ответ 5

Чтобы использовать несколько Jars в параметрах компилятора Maven, используйте строку ${path.separator} между банками:

<compilerArguments>
   <bootclasspath>${env.JAVA5_HOME}/jre/lib/rt.jar${path.separator}${env.JAVA5_HOME}/jre/lib/jce.jar${path.separator}${env.JAVA5_HOME}/jre/lib/jsse.jar</bootclasspath>
</compilerArguments>