Java-Versionen in Android-Builds

Unabhängig davon, ob Ihr Quellcode in Java, Kotlin oder beiden geschrieben ist, müssen Sie an verschiedenen Stellen eine JDK- oder Java-Sprachversion für Ihren Build auswählen.

Übersicht über JDK-Beziehungen in einem Gradle-Build

Glossar

Java Development Kit (JDK)
Das Java Development Kit (JDK) enthält Folgendes:
  • Tools wie Compiler, Profiler und Archiversteller. Sie werden im Hintergrund während des Builds verwendet, um Ihre Anwendung zu erstellen.
  • Bibliotheken mit APIs, die Sie über Ihren Kotlin- oder Java-Quellcode aufrufen können. Unter Android sind nicht alle Funktionen verfügbar.
  • Die Java Virtual Machine (JVM), ein Interpreter, der Java-Anwendungen ausführt. Sie verwenden die JVM, um die Android Studio IDE und das Gradle-Build-Tool auszuführen. Die JVM wird nicht auf Android-Geräten oder Emulatoren verwendet.
JetBrains-Laufzeit (JBR)
Die JetBrains-Laufzeit (JBR) ist ein optimiertes JDK, das mit Android Studio bereitgestellt wird. Sie enthält verschiedene Optimierungen zur Verwendung in Studio und verwandten JetBrains-Produkten, kann aber auch zum Ausführen anderer Java-Anwendungen verwendet werden.

Wie wähle ich ein JDK für die Ausführung von Android Studio aus?

Wir empfehlen die Verwendung von JBR, um Android Studio auszuführen. Es wird mit Android Studio bereitgestellt und genutzt, um Android Studio zu testen. Außerdem enthält es Verbesserungen für eine optimale Nutzung von Android Studio. Legen Sie daher nicht die Umgebungsvariable STUDIO_JDK fest.

Die Startskripts für Android Studio suchen in folgender Reihenfolge nach einer JVM:

  1. Umgebungsvariable STUDIO_JDK
  2. Verzeichnis studio.jdk (in der Android Studio-Distribution)
  3. jbr-Verzeichnis (JetBrains-Laufzeit) in der Android Studio-Distribution Empfohlen.
  4. Umgebungsvariable JDK_HOME
  5. Umgebungsvariable JAVA_HOME
  6. java in der Umgebungsvariable PATH ausführbar

Wie wähle ich aus, mit welchem JDK meine Gradle-Builds ausgeführt werden?

Wenn Sie Gradle über die Schaltflächen in Android Studio ausführen, wird Gradle über das in den Android Studio-Einstellungen festgelegte JDK ausgeführt. Wenn Sie Gradle in einem Terminal innerhalb oder außerhalb von Android Studio ausführen, bestimmt die Umgebungsvariable JAVA_HOME (falls festgelegt), in welchem JDK die Gradle-Skripts ausgeführt werden. Wenn JAVA_HOME nicht festgelegt ist, wird der Befehl java für die Umgebungsvariablen PATH verwendet.

Die konsistentesten Ergebnisse erhalten Sie, wenn Sie die Umgebungsvariable JAVA_HOME und die Gradle-JDK-Konfiguration in Android Studio auf dasselbe JDK festlegen.

Beim Ausführen des Builds erstellt Gradle einen Prozess, der als Daemon bezeichnet wird, um den eigentlichen Build auszuführen. Dieser Vorgang kann wiederverwendet werden, sofern die Builds dieselbe JDK- und Gradle-Version verwenden. Durch die Wiederverwendung eines Daemons wird die Zeit für den Start einer neuen JVM und die Initialisierung des Build-Systems verkürzt.

Wenn Sie Builds mit verschiedenen JDKs oder Gradle-Versionen starten, werden zusätzliche Daemons erstellt, die mehr CPU und Arbeitsspeicher verbrauchen.

Gradle-JDK-Konfiguration in Android Studio

Wenn Sie die Gradle-JDK-Konfiguration des vorhandenen Projekts ändern möchten, öffnen Sie die Gradle-Einstellungen unter Datei (oder Android Studio unter macOS) > Einstellungen > Build, Ausführung, Bereitstellung > Build-Tools > Gradle. Das Drop-down-Menü Gradle JDK enthält die folgenden Optionen zur Auswahl:

  • Makros wie JAVA_HOME und GRADLE_LOCAL_JAVA_HOME
  • JDK-Tabelleneinträge im vendor-version-Format wie jbr-17, die in den Android-Konfigurationsdateien gespeichert sind
  • JDK herunterladen
  • Bestimmtes JDK hinzufügen
  • Lokal erkannte JDKs aus dem standardmäßigen JDK-Installationsverzeichnis des Betriebssystems

Die ausgewählte Option wird in der Option gradleJvm in der Datei .idea/gradle.xml des Projekts gespeichert. Die Auflösung des JDK-Pfads wird verwendet, um Gradle auszuführen, wenn sie über Android Studio gestartet wird.

Abbildung 1. Gradle JDK-Einstellungen in Android Studio

Die Makros ermöglichen die Auswahl des dynamischen JDK-Projekts für das Projekt:

  • JAVA_HOME: verwendet die gleichnamige Umgebungsvariable
  • GRADLE_LOCAL_JAVA_HOME: verwendet das Attribut java.home in der Datei .gradle/config.properties, das standardmäßig die JetBrains-Laufzeit verwendet.

Das ausgewählte JDK wird verwendet, um beim Bearbeiten Ihrer Build-Skripts und des Quellcodes Ihren Gradle-Build auszuführen und JDK API-Referenzen aufzulösen. Die angegebene compileSdk schränkt außerdem ein, welche Java-Symbole beim Bearbeiten und Erstellen des Quellcodes verfügbar sind.

Wählen Sie eine JDK-Version aus, die höher oder gleich den JDK-Versionen ist, die von den Plug-ins in Ihrem Gradle-Build verwendet werden. Die erforderliche mindestens erforderliche JDK-Version für das Android-Gradle-Plug-in (AGP) finden Sie in der Kompatibilitätstabelle in den Versionshinweisen.

Für das Android-Gradle-Plug-in Version 8.x ist beispielsweise JDK 17 erforderlich. Wenn Sie versuchen, einen Gradle-Build auszuführen, der mit einer früheren Version des JDK verwendet wird, wird eine Meldung wie diese ausgegeben:

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

Welche Java APIs kann ich in meinem Java- oder Kotlin-Quellcode verwenden?

Eine Android-App kann einige der in einem JDK definierten APIs verwenden, aber nicht alle. Das Android SDK definiert Implementierungen vieler Java-Bibliotheksfunktionen als Teil der verfügbaren APIs. Die Eigenschaft compileSdk gibt an, welche Android SDK-Version beim Kompilieren des Kotlin- oder Java-Quellcodes verwendet werden soll.

Kotlin

android {
    ...
    compileSdk = 33
}

Cool

android {
    ...
    compileSdk 33
}

Jede Version von Android unterstützt eine bestimmte Version des JDK und einen Teil seiner verfügbaren Java APIs. Wenn Sie eine Java API verwenden, die in einer compileSdk verfügbar ist, die im angegebenen minSdk nicht verfügbar ist, können Sie die API möglicherweise in einer früheren Android-Version über einen Prozess verwenden, der als Desugaring bezeichnet wird. Informationen zu unterstützten APIs finden Sie unter Über die Deugaring-Funktion verfügbare Java 11+ APIs.

Anhand dieser Tabelle können Sie ermitteln, welche Java-Version von den einzelnen Android-APIs unterstützt wird und wo Sie Details zu den verfügbaren Java-APIs finden.

Android Java Unterstützte API- und Sprachfunktionen
14 (API 34) 17 Kernbibliotheken
13 (API 33) 11 Kernbibliotheken
12 (API 32) 11 Java API
11 und niedriger Android-Versionen

Welches JDK kompiliert meinen Java-Quellcode?

Das JDK für die Java-Toolchain enthält den Java-Compiler, der zum Kompilieren des Java-Quellcodes verwendet wird. Dieses JDK führt während des Builds auch javadoc und Unittests aus.

Die Toolchain verwendet standardmäßig das JDK, das zum Ausführen von Gradle verwendet wird. Wenn Sie die Standardeinstellung verwenden und einen Build auf verschiedenen Rechnern ausführen (z. B. auf Ihrem lokalen Computer und einem separaten Continuous Integration-Server), können die Ergebnisse Ihres Builds abweichen, wenn verschiedene JDK-Versionen verwendet werden.

Wenn Sie einen konsistenteren Build erstellen möchten, können Sie explizit eine Version der Java-Toolchain angeben. Angabe:

  • Ermittelt ein kompatibles JDK auf dem System, auf dem der Build ausgeführt wird.
    • Wenn kein kompatibles JDK vorhanden ist (und ein Toolchain-Resolver definiert ist), laden Sie eines herunter.
  • Stellt die Java-APIs der Toolchain für Aufrufe aus dem Quellcode bereit.
  • Kompiliert die Java-Quelle mit ihrer Java-Sprachversion.
  • Stellt Standardeinstellungen für sourceCompatibility und targetCompatibility bereit.

Wir empfehlen, immer die Java-Toolchain anzugeben und entweder das angegebene JDK zu installieren oder Ihrem Build einen Toolchain-Resolver hinzuzufügen.

Sie können die Toolchain unabhängig davon angeben, ob Ihr Quellcode in Java und/oder Kotlin geschrieben wurde. Geben Sie die Toolchain auf der obersten Ebene der build.gradle(.kts)-Datei Ihres Moduls an.

Geben Sie die Version der Java-Toolchain so an:

Kotlin

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

Cool

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

Das funktioniert, wenn Sie Kotlin, Java oder eine Kombination aus beidem verwenden.

Die JDK-Version der Toolchain kann mit dem JDK übereinstimmen, das zum Ausführen von Gradle verwendet wird. Sie dienen jedoch unterschiedlichen Zwecken.

Welche Quellfunktionen für die Java-Sprache kann ich in meinem Java-Quellcode verwenden?

Das Attribut sourceCompatibility bestimmt, welche Java-Sprachfunktionen während der Kompilierung der Java-Quelle verfügbar sind. Dies hat keine Auswirkungen auf die Kotlin-Quelle.

Wenn keine Angabe erfolgt, wird standardmäßig die Java-Toolchain oder JDK verwendet, die zum Ausführen von Gradle verwendet wird. Wir empfehlen, immer explizit eine Toolchain (bevorzugt) oder sourceCompatibility anzugeben.

Geben Sie sourceCompatibility in der Datei build.gradle(.kts) Ihres Moduls an.

Kotlin

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
    }
}

Cool

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

Welche Binärfunktionen von Java können verwendet werden, wenn ich meinen Kotlin- oder Java-Quellcode kompiliere?

Wenn Sie targetCompatibility und jvmTarget angeben, wird die Version im Java-Klassenformat festgelegt, die beim Generieren von Bytecode für die kompilierte Java- bzw. Kotlin-Quelle verwendet wird.

Einige Kotlin-Funktionen existierten bereits, bevor entsprechende Java-Funktionen hinzugefügt wurden. Frühe Kotlin-Compiler mussten eine eigene Methode entwickeln, um diese Kotlin-Funktionen darzustellen. Einige dieser Funktionen wurden später zu Java hinzugefügt. Bei späteren jvmTarget-Levels kann der Kotlin-Compiler die Java-Funktion möglicherweise direkt verwenden, was zu einer besseren Leistung führen kann.

targetCompatibility hat standardmäßig den gleichen Wert wie sourceCompatibility, muss aber größer oder gleich sourceCompatibility sein.

jvmTarget verwendet standardmäßig die Version der Toolchain.

Verschiedene Versionen von Android unterstützen verschiedene Java-Versionen. Sie können zusätzliche Java-Funktionen nutzen, indem Sie targetCompatibility und jvmTarget erhöhen. Möglicherweise müssen Sie dadurch aber auch Ihre Android SDK-Mindestversion erhöhen, damit die Funktion verfügbar ist.

Kotlin

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

Cool

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