--- SPOILER ALERT ---
Krótka odpowiedź jest taka, że w celu zestawienia źródło do starszej wersji, trzeba dostarczać zarówno opcję -source
jak również -bootclasspath
. Zobacz this article. A jeśli chcesz skompilować źródła do nowszej wersji, trzeba ustawić <source>
, <target>
, <compilerVersion>
, <fork>
i <executable>
na wtyczce kompilator i ustawić <jvm>
na wtyczce murowany ...
a teraz za historię ...
Wpadłem na ten sam problem. Okazuje się, że kompilowanie poprzedniej wersji może nie być tak proste jak ustawienie <source>
i <target>
. Mój konkretny przypadek jest taki, że mam JDK Java 1.7 i moja klasa ma niekompatybilność z 1.7 (dodali nową metodę do interfejsu, który implementuję). Kiedy próbowałem ją skompilować, kompilator dał mi komunikat o błędzie stwierdzający, że nie zaimplementowałem metody interfejsu. W każdym razie, próbowałem ustawić wtyczkę kompilatora:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
, ale po uruchomieniu kompilacji wystąpił ten sam błąd. Więc wpadłem Maven w debugowania i zobaczyłem to:
[INFO] [DEBUG] Command line options:
[INFO] [DEBUG] -d C:\... -nowarn -target 1.6 -source 1.6 -encoding UTF-8
Należy pamiętać, że ... jest umieścić w miejscu rzeczywistych argumentów dla zwięzłości
na wyjściu. Komunikat zaczynający się od -d
jest faktyczną pełną listą argumentów kompilacji. Tak więc, jeśli usunąć flagę -nowarn
i wklej odpoczynek po javac
w wierszu poleceń można zobaczyć rzeczywiste wyjście z kompilatora:
javac -d C:\... -target 1.6 -source 1.6 -encoding UTF-8
warning: [options] bootstrap class path not set in conjunction with -source 1.6
ten wypisuje handy-dandy ostrzegawczy bootstrap klasy ścieżki nie ustawiony w w połączeniu z -source 1.6. Trochę googling na który włącza się this article który stanowi:
To use javac from JDK N to cross-compiler to an older platform version, the correct practice is to:
- Use the older -source setting.
- Set the bootclasspath to compile against the rt.jar (or equivalent) for the older platform.
If the second step is not taken, javac will dutifully use the old language rules combined with new libraries, which can result in class files that do not work on the older platform since references to non-existent methods can get included.
Teraz przedstawieniu the maven documentation for the compiler plugin daje:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<compilerArguments>
<verbose />
<bootclasspath>${java.home}\lib\rt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
które można następnie połączyć ze swojej wcześniejszej konfiguracji, aby uzyskać:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<bootclasspath>${java.home}\lib\rt.jar</bootclasspath>
</configuration>
</plugin>
I teraz wystarczy udostępnić zmienną ${java.home}
dla swoich właściwości systemu mvn (przez -D systemu lub poprzez zwykły stare zmienne środowiskowe, lub możesz się naprawdę spodobać i umieścić go w profilu java 6 w ustawieniach użytkownika).
Teraz wystarczy uruchomić build i przejść chwycić zimne piwo podczas gdy chugs dala ...
---- EDIT ----
... Ostatnią rzeczą w tym rt.jar Twoja bootclasspath jest zawsze wymagana, jednak odkryłem, że więcej może być potrzebnych dla każdego przypadku. Musiałem dołączyć plik jce.jar (w tym samym katalogu, co rt.jar), ponieważ moja aplikacja pracowała przy kryptografii.
---- EDIT 2 ----
Dla uśmiechami, próbowałem go innym kierunku. Zamiast biegać Maven Java 7 kompilacji dla Java 6, wpadłem Maven Java 6 kompilacji Java 7. Pierwsza próba jest dość prosta:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<fork>true</fork>
<verbose>true</verbose>
<compilerVersion>1.7</compilerVersion>
<executable>${JAVA_7_HOME}/bin/javac</executable>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
Zasadniczo mogę ustawić <source>
i <target>
do 1,7, ale to oczywiście nie wystarczy, ponieważ 6 cant skompiluje 7 kodów. Wracając do wtyczki kompilatora, faktycznie jest an example page opisujące, co należy zrobić.Mianowicie, musisz <fork>
wyłączyć nowy proces, używając java 7 <executable>
. Więc teraz myślę, że wszystko gotowe. Czas odpalić budowy ...
C:\Projects\my-project>mvn package
...
Caused by: java.lang.UnsupportedClassVersionError: mypackage.StupidTest : Unsup
ported major.minor version 51.0
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
Co do cholery jest UnsupportedClassVersionError? Bliższe spojrzenie mówi nam o tym, że wtyczka maven-surefire nie działa. Więc próbuję tylko mvn compile
i na pewno osiągam sukces, ponieważ wtyczka "surefire" nigdy się nie uruchamia. Więc biegnę mvn -X package
i zauważy ten klejnot:
Forking command line: cmd.exe /X /C ""C:\Program Files\Java\jdk1.6.0_29\jre\bin\
java" -jar C:\Projects\my-project\target\surefire\surefirebooter2373372991878002
398.jar C:\Projects\my-project\target\surefire\surefire1861974777102399530tmp C:
\Projects\my-project\target\surefire\surefire4120025668267754796tmp"
Ok, więc jego bieg java 6. Dlaczego? Dokumentacja dla SureFire daje to:
jvm:
Option to specify the jvm (or path to the java executable) to use with the forking
options. For the default, the jvm will be a new instance of the same VM as the one
used to run Maven. JVM settings are not inherited from MAVEN_OPTS.
Ponieważ zabrakło mvn z Java 6 VM jej rozwidlenia na Java 6 VM dla swoich testów jednostkowych. Więc ustawienie tej opcji odpowiednio:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<jvm>${JAVA_7_HOME}/bin/java</jvm>
</configuration>
</plugin>
I rozpalania kompilacji ...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Jeśli spróbujesz uruchomić zwolnione słoiki w wersji 1.5, czy działają one w wersji 1.5? Czy otrzymasz nieważny wyjątek jar/corrupted jar, informujący o tym, że prawdopodobnie zostały skompilowane w nowszej wersji? – aperkins
Wygląda na to, że zarówno soki migawkowe, jak i wydań działają, działające w wersji 1.5. Nie dostaję jeszcze żadnego błędu, ale nie rozumiem, co sprawia, że klasy różnią się rozmiarem. Mam tylko nadzieję, że coś mi się nie podskoczy, kiedy to osiągnie produkcję. – IceGras
@IceGras, to może być niebezpieczne, wyjaśniam dlaczego w mojej odpowiedzi poniżej ... W skrócie, _referencje do nieistniejących metod mogą zostać włączone_ – Lucas