Android 建構作業中的 Java 版本

無論您的原始碼是以 Java 和/或 Kotlin 編寫,都必須在幾個地方為建構作業選擇 JDK 或 Java 語言版本。

Gradle 建構作業中的 JDK 關係總覽

詞彙解釋

Java Development Kit (JDK)
Java Development Kit (JDK) 包含:
  • 編譯器、分析器和封存建立工具等工具。可在建構期間的幕後使用來建立應用程式。
  • 包含可透過 Kotlin 或 Java 原始碼呼叫的 API。請注意,Android 並未提供所有函式。
  • Java 虛擬機器 (JVM) 是執行 Java 應用程式的解譯器。您可以使用 JVM 執行 Android Studio IDE 和 Gradle 建構工具。JVM 不會用於 Android 裝置或模擬器。
JetBrains 執行階段 (JBR)
JetBrains Runtime (JBR) 是隨附於 Android Studio 的強化版 JDK。其中包含多項可用於 Studio 和相關 JetBrains 產品的最佳化項目,但也可用於執行其他 Java 應用程式。

如何選擇 JDK 來執行 Android Studio?

建議您使用 JBR 執行 Android Studio。此 SDK 會配合 Android Studio 部署及用於測試,並提供改善 Android Studio 用量的強化功能。為了確保這一點,請勿設定 STUDIO_JDK 環境變數。

Android Studio 的開機指令碼會依照下列順序尋找 JVM:

  1. STUDIO_JDK 環境變數
  2. studio.jdk 目錄 (在 Android Studio 發行版本中)
  3. Android Studio 發行版中的 jbr 目錄 (JetBrains Runtime)。推薦影片。
  4. JDK_HOME 環境變數
  5. JAVA_HOME 環境變數
  6. PATH 環境變數中的 java 執行檔

如何選擇執行 Gradle 版本的 JDK?

如果您使用 Android Studio 中的按鈕執行 Gradle,則 Android Studio 設定中設定的 JDK 集會用於執行 Gradle。如果您是在 Android Studio 內部或外部的終端機執行 Gradle,JAVA_HOME 環境變數 (如有設定) 會決定哪個 JDK 會執行 Gradle 指令碼。如未設定 JAVA_HOME,系統會在 PATH 環境變數中使用 java 指令。

為取得最一致的結果,請務必設定 JAVA_HOME 環境變數,並將 Android Studio 中的 Gradle JDK 設為相同的 JDK。

執行建構時,Gradle 會建立一個名為Daemon 的程序來執行實際建構作業。只要建構作業使用相同的 JDK 和 Gradle 版本,即可重複使用這項程序。重複使用 Daemon 可以減少啟動新 JVM 及初始化建構系統的時間。

如果您使用不同的 JDK 或 Gradle 版本啟動建構,會建立額外的 Daemon,並耗用更多 CPU 和記憶體。

在 Android Studio 中設定 Gradle JDK

如要設定及下載 Android Studio 用來執行 Gradle 的 JDK,請依序前往「Settings」>「Build, Execution, Deployment」>「Build Tools」>「Gradle」,然後編輯「Gradle JDK」欄位。

選擇的 JDK 版本,應高於或等於 Gradle 建構作業中使用的外掛程式使用的 JDK 版本。如要判斷 Android Gradle 外掛程式 (AGP) 所需的最低 JDK 版本,請參閱版本資訊中的相容性表格。

舉例來說,Android Gradle 外掛程式 8.x 版需要 JDK 17。如果您嘗試執行的 Gradle 版本與舊版 JDK 搭配使用時,系統會回報如下的訊息:

An exception occurred applying plugin request [id: 'com.android.application']
> Failed to apply plugin 'com.android.internal.application'.
   > Android Gradle plugin requires Java 17 to run. You are currently using Java 11.
      Your current JDK is located in /usr/local/buildtools/java/jdk11
      You can try some of the following options:
       - changing the IDE settings.
       - changing the JAVA_HOME environment variable.
       - changing `org.gradle.java.home` in `gradle.properties`.

我可以在 Java 或 Kotlin 原始碼中使用哪些 Java API?

Android 應用程式可以使用 JDK 中定義的部分 API,但並非全部。Android SDK 會將許多 Java 程式庫函式的實作定義為可用的 API 的一部分。compileSdk 屬性會指定編譯 Kotlin 或 Java 原始碼時要使用的 Android SDK 版本。

Kotlin

android {
    ...
    compileSdk = 33
}

Groovy

android {
    ...
    compileSdk 33
}

每個 Android 版本都支援特定版本的 JDK,以及其可用的 Java API 子集。如果您使用的 Java API 包含在指定的 minSdk 中未提供的 Java API,則可透過稱為脫糖的程序在舊版 Android 中使用 API。compileSdk如要瞭解支援的 API,請參閱可透過脫糖程序使用的 Java 11 以上版本 API

請使用這個表格判斷每個 Android API 支援的 Java 版本,以及如何查看哪些 Java API 可用的詳細資料。

Android Java 支援的 API 和語言功能
14 (API 34) 17 核心程式庫
13 (API 33) 11 核心程式庫
12 (API 32) 11 Java API
11 以下版本 Android 版本

哪一個 JDK 會編譯 Java 原始碼?

Java 工具鍊 JDK 包含用於建構任何 Java 原始碼的 Java 編譯器。這個 JDK 也會執行 Kotlin 編譯器 (在 JVM 上執行)、javadoc,以及在建構期間執行的測試。

工具鍊預設為執行 Gradle 使用的 JDK。如果您使用預設值並在不同機器 (例如本機電腦和獨立的持續整合伺服器) 上執行建構作業,則如果使用不同 JDK 版本,建構作業的結果可能會有所不同。

如要建立更一致的版本,可以明確指定 Java 工具鍊版本。指定:

  • 在執行建構作業的系統中尋找相容的 JDK。
    • 如果沒有相容的 JDK (且已定義工具鍊解析器),請下載一個。
  • 公開用於從原始碼呼叫的工具鍊 Java API。
  • 使用 Java 語言版本編譯 Java 原始碼。
  • 提供 sourceCompatibilitytargetCompatibility 的預設值。

建議您一律指定 Java 工具鍊,並確保已安裝指定的 JDK,或者在建構作業中新增工具鍊解析器

無論原始碼是以 Java 和/或 Kotlin 編寫,您都可以指定工具鍊。在模組 build.gradle(.kts) 檔案的頂層指定工具鍊。

如果原始碼僅以 Java 編寫,請指定 Java 工具鍊版本,如下所示:

Kotlin

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

Groovy

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

如果來源只有 Kotlin,或混用 Kotlin 和 Java,請指定 Java 工具鍊版本,如下所示:

Kotlin

kotlin {
    jvmToolchain(17)
}

Groovy

kotlin {
    jvmToolchain 17
}

工具鍊 JDK 版本與用於執行 Gradle 的 JDK 版本相同,但請注意,其用途不同。

我可以在 Java 原始碼中使用哪些 Java 語言來源功能?

sourceCompatibility 屬性會決定在 Java 來源編譯期間可以使用哪些 Java 語言功能。這不會影響 Kotlin 來源。

如未指定,這會預設為執行 Gradle 的 Java 工具鍊或 JDK。建議您一律明確指定工具鍊 (建議選項) 或 sourceCompatibility

在模組的 build.gradle(.kts) 檔案中指定 sourceCompatibility

Kotlin

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
    }
}

Groovy

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

編譯 Kotlin 或 Java 原始碼時,可以使用哪些 Java 二進位功能?

指定 targetCompatibilityjvmTarget 可分別決定為已編譯的 Java 和 Kotlin 來源產生位元碼時使用的 Java 類別格式版本。

部分 Kotlin 功能在新增對等的 Java 功能之前就已存在。早期 Kotlin 編譯器必須建立自己的方式來代表這些 Kotlin 功能。其中一些功能之後會新增至 Java。隨著 jvmTarget 級別增加,Kotlin 編譯器可能會直接使用 Java 功能,因此可能會提升效能。

targetCompatibility 預設為和 sourceCompatibility 相同的值,但如有指定,值必須大於或等於 sourceCompatibility

jvmTarget 預設為工具鍊版本。

不同 Android 版本支援的 Java 版本各不相同。增加 targetCompatibilityjvmTarget 即可充分運用其他 Java 功能,但您可能也需要提高最低 Android SDK 版本,以確保功能可用。

Kotlin

android {
    compileOptions {
        targetCompatibility = JavaVersion.VERSION_17
    }
    kotlinOptions {
        jvmTarget = "17"
    }
}

Groovy

android {
    compileOptions {
        targetCompatibility JavaVersion.VERSION_17
    }
    kotlinOptions {
        jvmTarget '17'
    }
}