2010-09-03 6 views
14

Ich habe dieses Projekt aus mehreren Gläsern und Krieg gemacht, um ein Ohr zu machen. Ich baue alles in Schnappschuss und es funktioniert super. Dann machte ich eine Freigabe für jedes einzelne Projekt und sah, dass die Gläser und der Krieg in der Größe etwas anders als die Schnappschüsse waren.Maven Release-Plugin: Spezifizieren Sie Java-Compiler-Version

Beim Vergleichen von Datei zu Datei erkannte ich, dass die .class-Dateien alle da waren, aber etwas größer oder größer, im Allgemeinen nicht mehr als 40 Bytes.

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

ich diesen Tag für die Release-Plugin verwenden: mit diesem Tag in Maven

Ich zwinge Kompilation Java 1.5 verwenden

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-release-plugin</artifactId> 
    <version>2.0</version> 
    <configuration> 
     <releaseProfiles>release</releaseProfiles> 
     <goals>deploy</goals> 
    </configuration> 
</plugin> 

Könnte es sein, dass die Freigabe-Plugin kompiliert in 1.6 oder andere, erklären die Klassen Größenunterschied? Wenn ja, kann ich das Release-Plugin in 1.5 kompilieren?

Danke für Ihre Eingabe.

+0

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

+0

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

+0

@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

Antwort

1

Sie können die Version überprüfen, für die eine Klasse kompiliert wurde, indem Sie das im JDK enthaltene Dienstprogramm javap verwenden. Von der Befehlszeile:

javap -verbose MyClass 

In der Ausgabe von javap Look für „kleinere Version“ und „Hauptversion“ etwa zehn Zeilen nach unten.

Dann diese Tabelle verwenden:

 
major  minor  Java platform version 
45   3   1.0 
45   3   1.1 
46   0   1.2 
47   0   1.3 
48   0   1.4 
49   0   1.5 
50   0   1.6 

Die .class- Größenunterschied zurückzuführen sein kann Version kompilieren, aber auch mit Debug-Informationen (Zeilennummern in stacktraces) wie Kompilieren aufgrund anderer Kompilierungsoptionen sein kann.

+0

Auf macOS (mindestens 10.12.6), die Ausgabe von der ** Datei * * Befehl ist noch hilfreicher, z 'file MyClass.class' erzeugt möglicherweise:' MyClass.class: kompilierte Java-Klassendaten, Version 50.0 (Java 1.6) ' – Gary

0

Could it be that the release plugin is compiling in 1.6 or other, explaining the classes size difference ?

Kann nicht IMO sein. Das Maven Release Plugin kompiliert nichts, es löst nur eine Phase aus, die selbst die compile Phase und das Maven Compiler Plugin auslöst. Mit anderen Worten, das Maven Compiler Plugin und seine Einstellungen werden verwendet.

können Sie die folgenden Befehle verwenden, um zu steuern, was genau passiert:

mvn help:active-profiles -Prelease 

Profile zu überprüfen. Und

mvn help:effective-pom -Prelease 

, um die effektive Pom zu überprüfen.

+0

Ich habe das gleiche Problem. Ich habe '' und '' in meiner Pom-Datei als 1.6 angegeben. Wenn ich 'mvn package' starte, bekomme ich Erfolg. Wenn ich jedoch 'mvn release: prepare' starte, schlägt es mit 'TunneledDataSourceWrapper.java:[17,7] fehl. Error: TunneledDataSourceWrapper ist nicht abstrakt und überschreibt nicht die abstrakte Methode getParentLogger() in CommonDataSource', was ein Anzeichen dafür ist, dass es versucht Kompilieren von Java 7 _ (Java 7 hat CommonDataSource eine Methode hinzugefügt, die es mit 6 unvereinbar macht) _. – Lucas

18

--- 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] ------------------------------------------------------------------------ 
+0

Hat sich mit Java 8 etwas verändert? Ich baue mit einem Ziel von Java 6 und wenn ich 'bootclasspath' in meiner' pom.xml' setze, bekomme ich die gefürchtete 'Klassendatei hat die falsche Version 52.0, sollte 50.0 sein. Wenn ich * compilerArguments * entferne und nur "source" und "target" behalte, scheitert mein Build nicht. Das ist das genaue Gegenteil dieser Antwort. Mehr Details in dieser Frage: http://stackoverflow.com/questions/34854961/class-file-has-wrong-version-after-jenkins-upgrade –

+0

@AmedeeVanGasse, sorry, ich habe keine Kenntnis von etwas, das Java 8 verursachen würde sich anders verhalten als die obige Situation. – Lucas

+0

Egal. Ich vermute eine sehr alte Version des Maven-Compiler-Plugins, weil es genau wie in deinem Beispiel mit der aktuellen Version 3.3 und den Parametern genau so funktioniert wie in deinen Antworten. Am eigenartigsten, aber so sind die Feinheiten von Maven. –

0

Nur ein Hinweis, wenn eine falsche Version aufgenommen wird, erhalten Sie einen Fehler so etwas wie

bekommen
xxxx is not supported in -source 1.5 
[ERROR] (use -source 7 or higher to enable yyyy) 

Während maven release, maven release plugin (legt fest/Standardwerte) der Compiler-Version 1.5. Um sicherzustellen, dass die richtige Version abgerufen wird, geben Sie die Eigenschaften an.

<properties> 
<maven.compiler.source>1.7</maven.compiler.source> 
<maven.compiler.target>1.7</maven.compiler.target> 
</properties> 
Verwandte Themen