Java-Versionen in Android-Builds

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

JDK-Beziehungen in einem Gradle-Build
Abbildung 1. JDK-Beziehungen in einem Build

Glossar

Java Development Kit (JDK)
Das Java Development Kit (JDK) enthält:
  • Tools wie Compiler, Profiler und Archivierungsprogramme. Diese werden während des Builds im Hintergrund verwendet, um Ihre Anwendung zu erstellen.
  • Bibliotheken mit APIs, die Sie aus Ihrem Kotlin- oder Java-Quellcode aufrufen können. Hinweis: Nicht alle Funktionen sind auf Android-Geräten verfügbar.
  • Die Java Virtual Machine (JVM), ein Interpreter, der Java-Anwendungen ausführt. Mit der JVM können Sie die Android Studio IDE und das Gradle-Build-Tool ausführen. Die JVM wird nicht auf Android-Geräten oder ‑Emulatoren verwendet.
JetBrains Runtime (JBR)
Die JetBrains Runtime (JBR) ist ein erweitertes JDK, das mit Android Studio ausgeliefert wird. Sie enthält mehrere Optimierungen für die Verwendung in Studio und ähnlichen 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, Android Studio mit dem JBR auszuführen. Es wird mit Android Studio bereitgestellt und zum Testen von Android Studio verwendet. Außerdem enthält es Verbesserungen für die optimale Nutzung von Android Studio. Legen Sie dazu die Umgebungsvariable STUDIO_JDK nicht fest.

Die Startscripts für Android Studio suchen in der folgenden Reihenfolge nach einer JVM:

  1. Umgebungsvariable STUDIO_JDK
  2. studio.jdk-Verzeichnis (in der Android Studio-Distribution)
  3. jbr-Verzeichnis (JetBrains Runtime) in der Android Studio-Distribution. Empfohlen.
  4. Umgebungsvariable JDK_HOME
  5. Umgebungsvariable JAVA_HOME
  6. java-Ausführbares Programm in der Umgebungsvariablen PATH

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 das in den Android Studio-Einstellungen festgelegte JDK verwendet, um Gradle auszuführen. Wenn Sie Gradle in einem Terminal ausführen, entweder innerhalb oder außerhalb von Android Studio, wird mit der Umgebungsvariablen JAVA_HOME (falls festgelegt) festgelegt, mit welchem JDK die Gradle-Scripts ausgeführt werden. Wenn JAVA_HOME nicht festgelegt ist, wird der Befehl java auf die Umgebungsvariable PATH angewendet.

Für möglichst einheitliche Ergebnisse sollten Sie die Umgebungsvariable JAVA_HOME und die Gradle-JDK-Konfiguration in Android Studio auf dasselbe JDK festlegen.

Wenn Sie den Build ausführen, erstellt Gradle einen Prozess namens Daemon, um den eigentlichen Build auszuführen. Dieser Prozess kann wiederverwendet werden, solange die Builds dieselbe JDK- und Gradle-Version verwenden. Durch die Wiederverwendung eines Daemons wird die Zeit verkürzt, die zum Starten einer neuen JVM und zum Initialisieren des Build-Systems erforderlich ist.

Wenn Sie Builds mit verschiedenen JDK- 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:

  • 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 Standardinstallationsverzeichnis für JDKs des Betriebssystems

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

Abbildung 2. Gradle-JDK-Einstellungen in Android Studio

Mit den Makros können Sie den JDK-Pfad für dynamische Projekte auswählen:

  • JAVA_HOME: die Umgebungsvariable mit demselben Namen verwendet
  • GRADLE_LOCAL_JAVA_HOME: Die java.home-Eigenschaft in der .gradle/config.properties-Datei wird verwendet. Standardmäßig ist dies die JetBrains-Laufzeit.

Das ausgewählte JDK wird verwendet, um Ihren Gradle-Build auszuführen und JDK API-Referenzen beim Bearbeiten Ihrer Build-Scripts und des Quellcodes aufzulösen. Beachten Sie, dass die angegebene compileSdk weiter einschränkt, welche Java-Symbole beim Bearbeiten und Erstellen des Quellcodes verfügbar sind.

Wählen Sie eine JDK-Version aus, die mindestens der JDK-Version entspricht, die von den Plugins verwendet wird, die Sie in Ihrem Gradle-Build verwenden. Die Mindestversion des JDK für das Android Gradle-Plug-in (AGP) finden Sie in der Kompatibilitätstabelle in den Versionshinweisen.

Für das Android-Gradle-Plug-in in Version 8.x ist beispielsweise JDK 17 erforderlich. Wenn Sie versuchen, einen Gradle-Build auszuführen, der es mit einer älteren JDK-Version verwendet, wird eine Meldung wie die folgende 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/jdk
      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-Anwendung kann einige der in einem JDK definierten APIs verwenden, aber nicht alle. Das Android SDK definiert als Teil seiner verfügbaren APIs Implementierungen vieler Java-Bibliotheksfunktionen. Mit der Eigenschaft compileSdk wird angegeben, welche Android SDK-Version beim Kompilieren Ihres Kotlin- oder Java-Quellcodes verwendet werden soll.

Kotlin

android {
    ...
    compileSdk = 33
}

Groovy

android {
    ...
    compileSdk 33
}

Jede Android-Version unterstützt eine bestimmte Version des JDK und einen Teil der verfügbaren Java APIs. Wenn Sie eine Java-API verwenden, die in einer compileSdk verfügbar ist, die nicht in der angegebenen minSdk verfügbar ist, können Sie die API möglicherweise in der älteren Android-Version verwenden. Dazu wird ein Prozess namens Desugaring verwendet. Informationen zu unterstützten APIs finden Sie unter Java 11 und höher – APIs, die durch Desugaring verfügbar sind.

In dieser Tabelle sehen Sie, 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

Mit welchem JDK wird mein Java-Quellcode kompiliert?

Das JDK der Java-Toolchain enthält den Java-Compiler, mit dem Java-Quellcode kompiliert wird. Dieses JDK führt während des Builds auch Javadoc- und Unit-Tests aus.

Die Toolbox verwendet standardmäßig das JDK, mit dem Gradle ausgeführt wird. Wenn Sie die Standardeinstellung verwenden und einen Build auf verschiedenen Maschinen ausführen (z. B. auf Ihrem lokalen Computer und einem separaten Continuous Integration-Server), können sich die Ergebnisse des Builds unterscheiden, wenn unterschiedliche JDK-Versionen verwendet werden.

Wenn Sie einen einheitlicheren Build erstellen möchten, können Sie eine Java-Toolchain-Version explizit angeben. Geben Sie Folgendes an:

  • Sucht auf dem System, auf dem der Build ausgeführt wird, nach einem kompatiblen JDK.
    • Wenn kein kompatibles JDK vorhanden ist (und ein Toolchain-Resolver definiert ist), wird ein solches heruntergeladen.
  • Stellt die Java-APIs der Toolchain für Aufrufe aus dem Quellcode bereit.
  • Kompiliert Java-Quellcode mit der entsprechenden Java-Sprachversion.
  • Standardeinstellungen für Tierbedarf für sourceCompatibility und targetCompatibility

Wir empfehlen, immer die Java-Toolchain anzugeben und entweder dafür zu sorgen, dass das angegebene JDK installiert ist, oder Ihrem Build einen Toolchain-Resolver hinzuzufügen.

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

Geben Sie die Java-Toolchain-Version so an:

Kotlin

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

Groovy

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

Das funktioniert, wenn Ihre Quelle Kotlin, Java oder eine Mischung aus beiden ist.

Die JDK-Version der Toolchain kann mit der JDK-Version übereinstimmen, die zum Ausführen von Gradle verwendet wird. Beachten Sie jedoch, dass sie unterschiedliche Zwecke erfüllen.

Welche Java-Quellcodefunktionen kann ich in meinem Java-Quellcode verwenden?

Mit der Eigenschaft sourceCompatibility wird festgelegt, welche Java-Sprachfunktionen bei der Kompilierung der Java-Quelldatei verfügbar sind. Das betrifft nicht die Kotlin-Quellcodes.

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

Kotlin

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
    }
}

Groovy

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

Wenn diese Eigenschaft nicht angegeben ist, wird standardmäßig die Version der Java-Toolchain verwendet. Wenn Sie keine Java-Toolchain verwenden, wird standardmäßig eine Version verwendet, die vom Android Gradle-Plug-in ausgewählt wird (z. B. Java 8 oder höher).

Welche Java-Binärfunktionen kann ich beim Kompilieren meiner Kotlin- oder Java-Quelle verwenden?

Die Eigenschaften targetCompatibility und jvmTarget geben die Version des Java-Klassenformats an, die beim Generieren von Bytecode für kompilierte Java- und Kotlin-Quellcodes verwendet wird.

Einige Kotlin-Funktionen gab es schon, bevor entsprechende Java-Funktionen hinzugefügt wurden. Frühe Kotlin-Compiler mussten ihre eigenen Methoden zur Darstellung dieser Kotlin-Funktionen entwickeln. Einige dieser Funktionen wurden später in Java hinzugefügt. Bei höheren jvmTarget-Stufen verwendet der Kotlin-Compiler möglicherweise direkt die Java-Funktion, was zu einer besseren Leistung führen kann.

Unterschiedliche Android-Versionen unterstützen unterschiedliche Java-Versionen. Wenn Sie targetCompatibility und jvmTarget erhöhen, können Sie zusätzliche Java-Funktionen nutzen. Möglicherweise müssen Sie dann aber auch die Mindest-Android-SDK-Version erhöhen, damit die Funktion verfügbar ist.

targetCompatibility muss größer oder gleich sourceCompatibility sein. In der Praxis sollte für sourceCompatibility, targetCompatibility und jvmTarget in der Regel derselbe Wert verwendet werden. Sie können sie so festlegen:

Kotlin

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

Groovy

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

Wenn diese Eigenschaften nicht angegeben sind, wird standardmäßig die Version der Java-Toolchain verwendet. Wenn Sie keine Java-Toolchain verwenden, können die Standardwerte abweichen und zu Build-Problemen führen. Wir empfehlen daher, diese Werte immer explizit anzugeben oder eine Java-Toolchain zu verwenden.