---尾翼警報---
簡短的回答是,爲了編譯源舊版本,你需要在兩個還有-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] ------------------------------------------------------------------------
如果您嘗試運行1.5版本中發佈的jar,它們是否運行在1.5版本?或者你會得到一個無效的jar /損壞的jar異常,告訴你他們很可能在更高版本上編譯? – aperkins 2010-09-03 19:48:16
快照和釋放罐似乎都在工作,運行在1.5。我還沒有得到任何錯誤,但我不明白是什麼使這些類的大小不同。我希望在達到產量時有些東西不會跳到我身上。 – IceGras 2010-09-03 20:16:35
@IceGras,它可能是危險的,我解釋了爲什麼在我的答案下面...總之,_reference不存在的方法可以包括_ – Lucas 2012-07-12 23:36:09