15

I have this project made of multiple jars and war to make an ear. I build everything in snapshot and it works great. Then I made a release for every single project and saw that the jars and the war were slightly different in size than the snapshot ones.

Comparing file to file I realized that the .class files were all there, but slightly larger or bigger, nothing more than 40 bytes generally.

I force compilation to use java 1.5 using this tag in Maven:

<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>

I use this tag for the release plugin:

<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>

Could it be that the release plugin is compiling in 1.6 or other, explaining the classes size difference ? If so can I make the release plugin compile in 1.5 ?

Thanks for your input.

4

4 に答える 4

19

- - スポイラー警告 - -

簡単に言えば、ソースを古いバージョンにコンパイルするには、-sourceオプションと-bootclasspath. この記事を参照してください。また、ソースを新しいバージョンにコンパイルする場合は、コンパイラ プラグインで 、 、 、 、<source>および<target><compilerVersion>設定<fork> surefireプラグインで設定する必要があります...<executable><jvm>

そして今、物語のために...

私は同じ問題に遭遇しました。<source>以前のバージョンをコンパイルするのは、とを設定するほど簡単ではないことがわかりまし<target>た。私の特定のケースは、Java 1.7 JDK を使用していて、私のクラスが 1.7 と非互換であることです(私が実装しているインターフェースに新しいメソッドが追加されました)。コンパイルしようとすると、インターフェイス メソッドが実装されていないことを示すエラー メッセージがコンパイラから表示されました。とにかく、コンパイラプラグインを設定してみました:

  <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>

しかし、ビルドを実行すると、同じエラーが発生しました。だから私はデバッグでmavenを実行し、これを見ました:

[INFO] [DEBUG] Command line options:
[INFO] [DEBUG] -d C:\... -nowarn -target 1.6 -source 1.6 -encoding UTF-8

... は、簡潔にするために実際の引数の代わりに配置されていることに注意してください。

出力で。で始まるメッセージ-dは、実際の完全なコンパイル引数リストです。そのため、フラグを削除し-nowarnて残りをjavacコマンド ラインに貼り付けると、コンパイラからの実際の出力を確認できます。

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

これは、 -source 1.6 と組み合わせて設定されていない便利な警告ブートストラップ クラス パスを出力します。それについて少しグーグルすると、次のように述べているこの記事が表示されます。

JDK N から古いプラットフォーム バージョンへのクロスコンパイラに javac を使用する正しい方法は次のとおりです。

  • 古い -source 設定を使用します。
  • 古いプラットフォームの rt.jar (または同等のもの) に対してコンパイルするように bootclasspath を設定します。

2 番目の手順を実行しない場合、javac は古い言語規則を新しいライブラリと組み合わせて忠実に使用します。これにより、存在しないメソッドへの参照が含まれる可能性があるため、古いプラットフォームでは機能しないクラス ファイルが作成される可能性があります。

コンパイラプラグインのMavenドキュメントを参照すると、次のようになります。

  <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>

これを以前の構成と組み合わせて、次を取得できます。

  <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>

次に、変数を mvn で使用できるようにする必要があり${java.home}ます (-D システム プロパティを使用するか、単純な古い環境変数を使用するか、ユーザー設定の Java 6 プロファイルに非常に凝って詰め込むことができます)。

ビルドを実行して、冷えたビールを飲みに行きましょう...

- - 編集 - -

最後にもう 1 つ... bootclasspath に rt.jar を含めることは常に必要ですが、ケースバイケースでさらに必要になる場合があることを発見しました。アプリが暗号化作業を行っていたため、(rt.jar と同じディレクトリに) jce.jar を含める必要がありました。

---- 編集 2 ----

笑顔のために、私はそれを別の方向に試しました. Java 6 用にコンパイルした Java 7 を使用して Maven を実行する代わりに、Java 7 用にコンパイルした Java 6 を使用して Maven を実行しました。

  <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>

基本的に、私は<source>and<target>を 1.7 に設定しましたが、6 は 7 のコードをコンパイルできないため、明らかにそれだけでは十分ではありません。コンパイラプラグインに戻ると、実際には何をする必要があるかを説明するサンプルページがあります。<fork>つまり、 Java 7 を使用して新しいプロセスをオフにする必要があります<executable>。だから今、私はすべての準備ができていると思います。ビルドを起動する時間です...

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

UnsupportedClassVersionError とは一体何ですか? よく見ると、失敗しているのは maven-surefire-plugin であることがわかります。したがってmvn compile、確実なプラグインが決して起動しないので、成功することを確認してください。だから私はmvn -X packageこの宝石を実行して気づきました:

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、それで Java 6 を実行しています。なぜですか? 確実なドキュメントには、次のように記載されています。

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.

mvn を Java 6 VM で実行したため、単体テストのために Java 6 VM をフォークしました。したがって、このオプションを適切に設定します。

  <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>

そして、ビルドを起動します...

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
于 2012-07-12T23:23:17.020 に答える
1

JDK に含まれている javap ユーティリティを使用して、クラスがコンパイルされているバージョンを確認できます。コマンドラインから:

javap -verbose MyClass

javap の出力で、約 10 行下の「マイナー バージョン」と「メジャー バージョン」を探します。

次に、このテーブルを使用します。

メジャー マイナー Java プラットフォーム バージョン
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

.class サイズの違いは、コンパイル バージョンが原因である可能性がありますが、デバッグ情報 (スタック トレースの行番号) を使用してコンパイルするなど、他のコンパイル オプションが原因である可能性もあります。

于 2010-09-03T20:14:38.100 に答える
0

リリース プラグインが 1.6 などでコンパイルされている可能性があり、クラス サイズの違いを説明していますか?

IMOにはなれません。compileMaven リリース プラグインは何もコンパイルしません。それ自体がフェーズと Maven コンパイラ プラグインをトリガーするフェーズをトリガーするだけです。つまり、Maven Compiler Plugin とその設定が使用されます。

次のコマンドを使用して、何が起こっているかを正確に制御できます。

mvn help:active-profiles -Prelease

プロファイルを確認します。と

mvn help:effective-pom -Prelease

有効なポンを確認します。

于 2010-09-03T22:53:12.833 に答える