--- SPOILER ALERT ---
Die kurze Antwort ist, dass, um Quelle zu einer älteren Version zu kompilieren Sie sowohl die -source
Option sowie die -bootclasspath
liefern müssen. Siehe this article. Und wenn Sie Quelle auf eine neuere Version kompilieren wollen, müssen Sie <source>
setzen, <target>
, <compilerVersion>
, <fork>
und <executable>
auf der Compiler-Plugin, und gesetzt <jvm>
auf der todsicheren Plugin ...
und jetzt für die Geschichte ...
Ich stieß auf das gleiche Problem. Es stellt sich heraus, dass das Kompilieren einer früheren Version möglicherweise nicht so einfach ist wie das Setzen von <source>
und <target>
. Mein spezieller Fall ist, dass ich ein Java 1.7 JDK habe und ich meine Klasse eine Inkompatibilität mit 1.7 habe (sie fügten eine neue Methode zu einer Schnittstelle hinzu, die ich implementiere). Als ich es kompilieren wollte, gab mir der Compiler eine Fehlermeldung, dass ich die Interface-Methode nicht implementiert hatte. Wie auch immer, ich habe versucht, das Compiler-Plugin zu setzen:
aber wenn ich den Build lief, bekam ich den gleichen Fehler Also lief ich Maven in Debug- und sah dies:
[INFO] [DEBUG] Command line options:
[INFO] [DEBUG] -d C:\... -nowarn -target 1.6 -source 1.6 -encoding UTF-8
Beachten Sie, dass die ... anstelle der tatsächlichen Argumente aus Gründen der Kürze gestellt wird
in der Ausgabe. Die Nachricht, die mit -d
beginnt, ist die tatsächliche vollständige Kompilierungsargumentliste. Also, wenn Sie die -nowarn
Flagge entfernen und fügen Sie den Rest nach javac
auf der Kommandozeile können Sie die aktuelle Ausgabe des Compilers sehen:
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
Dies gibt den Handy-Dandy Warnung Bootstrap-Classpath nicht gesetzt in Verbindung mit -source 1.6. Ein wenig Googeln auf, dass auftaucht this article in dem es heißt:
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.
Jetzt the maven documentation for the compiler plugin Referenzierung gibt:
<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>
die Sie dann mit Ihrer früheren Konfiguration kombinieren zu bekommen:
<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>
Und Jetzt müssen Sie nur noch die Variable ${java.home}
Ihrem MVN zur Verfügung stellen (über -D Systemeigenschaften oder über plain alte Umgebungsvariablen, oder Sie könnten wirklich schick werden und es in einem Java 6-Profil in Ihren Benutzereinstellungen stopfen.
Jetzt brauchen Sie nur Ihren Build laufen und ein kaltes Bier gehen zu ergreifen, während es weg tuckert ...
---- ---- EDIT
Eine letzte Sache ... Einschließlich rt.jar in Ihr bootclasspath ist immer erforderlich, aber ich entdeckte, dass mehr von Fall zu Fall mehr benötigt werden kann. Ich musste jce.jar (im selben Verzeichnis wie rt.jar) einbinden, weil meine App Krypto-Arbeit machte.
---- EDIT 2 ----
Für grinst, versuchte ich es in die andere Richtung. Stattdessen Maven des Laufens mit Java 7 für Java kompilieren 6, lief ich Maven mit Java 6 Kompilieren für Java 7. Der erste Versuch ziemlich geradlinig ist:
<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>
Grundsätzlich ich meine <source>
und <target>
-1,7 gesetzt, aber das wäre eindeutig nicht genug, denn 6 kompilieren 7 code nicht. Zurück zum Compiler-Plugin, gibt es eigentlich an example page was zu tun ist.Nämlich, müssen Sie <fork>
aus einem neuen Prozess mit dem Java 7 <executable>
. Jetzt denke ich, ich bin fertig. Zeit, um den Build zu starten ...
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] ------------------------------------------------------------------------
Was zum Teufel ist UnsupportedClassVersionError? Ein genauerer Blick sagt uns, dass das Maven-Surefire-Plugin fehlschlägt. Also versuche ich einfach mvn compile
und sicher genug, dass ich einen Erfolg habe, da das todsichere Plugin nie gefeuert hat. So laufe ich mvn -X package
und dieses Juwel bemerken:
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, so dass ihr die Ausführung von Java 6. Warum? Die Dokumentation für todsicheres ergibt dies:
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.
Da wir mvn mit einem Java 6 VM seines Forking eine Java 6 VM für seine Unit-Tests liefen. So Setzen Sie diese Option entsprechend:
<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>
Und die Build Anheizen ...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Wenn Sie versuchen und die freigegebenen Gläser in 1.5 ausführen, laufen sie in 1.5? Oder erhalten Sie eine ungültige jar/beschädigte jar-Ausnahme, die Ihnen mitteilt, dass sie wahrscheinlich auf einer späteren Version kompiliert wurde? – aperkins
Snapshot- und Release-Jars scheinen zu funktionieren und laufen in 1.5. Ich bekomme noch keinen Fehler, aber ich verstehe nicht, was die Klassen unterschiedlich groß macht. Ich hoffe nur, dass etwas nicht auf mich überspringen wird, wenn dies die Produktion erreicht. – IceGras
@IceGras, könnte es gefährlich sein, erkläre ich warum in meiner Antwort unten ... Kurz gesagt, _references zu nicht existenten Methoden können erhalten werden_ – Lucas