2010-09-03 101 views
14

我有這個項目由多個瓶子和戰爭做成耳朵。我在快照中構建所有內容,效果很好。然後,我爲每個單獨的項目發佈了一個版本,並且看到這些罐子和戰爭的尺寸與快照的尺寸略有不同。Maven發佈插件:指定java編譯器版本

比較文件到文件我意識到.class文件都在那裏,但稍大或稍大,一般不超過40字節。

我強迫編譯使用Maven的這個標籤使用的Java 1.5:

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

我使用這個標記爲發佈插件:

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

難道釋放插件正在編制中1.6或其他,解釋類的大小差異?如果是這樣,我可以使發佈插件在1.5編譯?

感謝您的輸入。

+0

如果您嘗試運行1.5版本中發佈的jar,它們是否運行在1.5版本?或者你會得到一個無效的jar /損壞的jar異常,告訴你他們很可能在更高版本上編譯? – aperkins 2010-09-03 19:48:16

+0

快照和釋放罐似乎都在工作,運行在1.5。我還沒有得到任何錯誤,但我不明白是什麼使這些類的大小不同。我希望在達到產量時有些東西不會跳到我身上。 – IceGras 2010-09-03 20:16:35

+0

@IceGras,它可能是危險的,我解釋了爲什麼在我的答案下面...總之,_reference不存在的方法可以包括_ – Lucas 2012-07-12 23:36:09

回答

1

您可以通過使用JDK附帶的javap實用程序來驗證類的編譯版本。從命令行:

javap -verbose MyClass 

在輸出javap尋找「次要版本」和「主要版本」約十行下來。

然後用這個表:

 
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 

的大小的.class差異可能是由於編譯的版本,但也可能是由於像調試信息編譯其他編譯選項(在蹤跡行號)。

+0

在macOS(至少10.12.6),從**文件* *命令更有幫助,例如'文件MyClass.class'可能產生:'MyClass.class:編譯的Java類數據,版本50.0(Java 1.6)' – Gary 2017-08-22 18:17:40

0

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

不能是IMO。 Maven Release Plugin不編譯任何東西,它只是觸發一個階段,它本身會觸發compile階段和Maven編譯器插件。換句話說,Maven編譯器插件及其設置將被使用。

您可以使用下面的命令來控制究竟是什麼發生了:

mvn help:active-profiles -Prelease 

檢查配置文件。並且

mvn help:effective-pom -Prelease 

檢查有效的pom。

+0

我有同樣的問題。我在我的pom文件中將''和''指定爲1.6。當我運行'mvn package'時,我獲得了成功。然而,當我運行'mvn release:prepare'時,它會失敗並顯示'TunneledDataSourceWrapper.java:[17,7]錯誤:TunneledDataSourceWrapper不是抽象的,也不會覆蓋CommonDataSource中的抽象方法getParentLogger(),這表明它正在嘗試編譯java 7 _(java 7爲CommonDataSource添加了一個方法,使其與6不兼容)_。 – Lucas 2012-07-12 21:55:44

18

---尾翼警報---

簡短的回答是,爲了編譯源舊版本,你需要在兩個還有-bootclasspath提供-source選項。請參閱this article。如果你想編譯源到新的版本,你需要設置<source><target><compilerVersion><fork>,並<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開始的消息是實際的完整編譯參數列表。所以,如果你javac後刪除-nowarn標誌粘貼其餘在命令行中,你可以看到實際的輸出從編譯器:

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聯合。對一個小Googling變成了this article其中規定:

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.

現在引用the maven documentation for the compiler plugin給出:

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

而且現在您只需要使${java.home}變量可用於您的mvn(通過-D系統屬性或通過純文本舊的環境變量,或者你可以變得很花哨,並把它放在用戶設置中的java 6配置文件中)。

現在只需運行構建和去抓住冰涼的啤酒,同時它一班班了......

---- ----編輯

最後一件事...包括在rt.jar中你的引導類路徑是總是需要,但是,我發現可能需要逐個更多的情況。我必須包含jce.jar(與rt.jar位於同一目錄中),因爲我的應用程序正在執行加密工作。

----編輯2 ----

對於咧嘴笑,我嘗試了另一個方向。相反,用java編譯7對Java 6運行Maven的,我跑行家用java編譯6對Java 7的第一次嘗試是非常直截了當:

<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><target>到1.7,但這顯然是不夠的,因爲6無法編譯7代碼。回到編譯器插件,實際上有an example page描述了需要完成的工作。也就是說,您需要使用java 7 <executable>關閉一個新進程<fork>。所以現在我覺得我全都定了。時間火燒建設...

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

什麼是不支持的ClassVersionError?仔細觀察告訴我們它的失敗的maven-surefire插件。所以我只嘗試mvn compile,果然我獲得了成功,因爲surefire插件從未激發過。所以,我跑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" 

好了,所以它的運行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. 

因爲我們有一個Java VM 6 MVN跑了分叉一個Java VM 6爲它的單元測試。因此,適當地設置這個選項:

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

Java 8有什麼變化嗎?我正在構建一個Java 6的目標,如果我在''pom.xml'中設置'bootclasspath',那麼可怕的'class文件的版本是52.0,應該是50.0'。當我*刪除*'compilerArguments'並且只保留'source'和'target'時,我的構建不會失敗。這與此答案完全相反。在這個問題的更多細節:http://stackoverflow.com/questions/34854961/class-file-has-wrong-version-after-jenkins-upgrade – 2016-01-18 15:40:35

+0

@AmedeeVanGasse,對不起,我不知道會導致Java 8的東西行爲與上述情況不同。 – Lucas 2016-01-18 21:01:51

+0

不管。我懷疑是Maven編譯器插件的一個非常舊的版本,因爲它的工作原理與當前版本3.3的示例完全一樣,並且參數與您的答案完全相同。最奇特的,但這是Maven的微妙之處。 – 2016-01-18 21:57:27

0

剛一說明,如果錯誤版本的回升,你會得到一個錯誤類似

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

在Maven發佈期間,Maven發佈插件(設置/默認爲)編譯器版本1.5。爲了確保它拿起正確的版本,請指定屬性。

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