編譯不同版本的 Java

Java 程式語言(及其執行時)自其首次公開發布以來發布以來經歷了許多變化。這些變化包括:

  • Java 程式語言語法和語義的變化
  • Java 標準類庫提供的 API 的更改。
  • Java(位元組碼)指令集和類檔案格式的更改。

除了極少數例外(例如 enum 關鍵字,對某些內部類的更改等),這些更改是向後相容的。

  • 使用較舊版本的 Java 工具鏈編譯的 Java 程式將在較新版本的 Java 平臺上執行,無需重新編譯。
  • 使用舊版 Java 編寫的 Java 程式將使用新的 Java 編譯器成功編譯。

使用較新的編譯器編譯舊 Java

如果你需要(重新)在較新的 Java 平臺上編譯較舊的 Java 程式碼以在較新的平臺上執行,則通常不需要提供任何特殊的編譯標誌。在少數情況下(例如,如果你使用 enum 作為識別符號),你可以使用 -source 選項來禁用新語法。例如,給定以下類:

public class OldSyntax {
    private static int enum;  // invalid in Java 5 or later
}

使用 Java 5 編譯器(或更高版本)編譯類需要以下內容:

$ javac -source 1.4 OldSyntax.java

編譯舊的執行平臺

如果需要編譯 Java 以在較舊的 Java 平臺上執行,最簡單的方法是為需要支援的最舊版本安裝 JDK,並在構建中使用該 JDK 的編譯器。

你也可以使用較新的 Java 編譯器進行編譯,但這很複雜。首先,必須滿足一些重要的先決條件:

  • 你編譯的程式碼不得使用你所定位的 Java 版本中不可用的 Java 語言結構。
  • 程式碼不能依賴於舊平臺中不可用的標準 Java 類,欄位,方法等。
  • 程式碼所依賴的第三方庫也必須為較舊的平臺構建,並在編譯時和執行時可用。

在滿足前提條件的情況下,你可以使用 -target 選項重新編譯舊平臺的程式碼。例如,

$ javac -target 1.4 SomeClass.java

將編譯上面的類以生成與 Java 1.4 或更高版本 JVM 相容的位元組碼。 (實際上,-source 選項意味著相容的 -target,因此 javac -source 1.4 ... 會產生相同的效果。在 Oracle 文件中描述了 -source-target 之間的關係。)

話雖如此,如果你只是使用 -target-source,你仍然會編譯編譯器的 JDK 提供的標準類庫。如果你不小心,最終可能會得到具有正確位元組碼版本的類,但依賴於不可用的 API。解決方案是使用 -bootclasspath 選項。例如:

$ javac -target 1.4 --bootclasspath path/to/java1.4/rt.jar SomeClass.java

將針對另一組執行時庫進行編譯。如果正在編譯的類具有(意外)依賴於較新的庫,則會給出編譯錯誤。