Java-Versionen in Android-Builds

Unabhängig davon, ob Ihr Quellcode in Java, Kotlin oder beidem geschrieben ist, müssen Sie an mehreren 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:
  • Tools wie Compiler, Profiler und Archiversteller. 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. Beachten Sie, dass unter Android nicht alle Funktionen verfügbar sind.
  • 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 erweitertes JDK, das mit Android Studio vertrieben wird. Sie umfasst verschiedene Optimierungen für Studio und verwandte JetBrains-Produkte, kann aber auch für andere Java-Anwendungen genutzt werden.

Wie wähle ich ein JDK zur Ausführung von Android Studio aus?

Wir empfehlen die Verwendung des JBR zur Ausführung von Android Studio. Sie wird mit Android Studio bereitgestellt und zum Testen verwendet und enthält Verbesserungen für eine optimale Nutzung von Android Studio. Legen Sie dazu nicht die Umgebungsvariable STUDIO_JDK fest.

Die Startskripts für Android Studio suchen in der folgenden 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 an. Empfohlen
  4. Umgebungsvariable JDK_HOME
  5. Umgebungsvariable JAVA_HOME
  6. Ausführbare Datei java in der Umgebungsvariablen PATH

Wie wähle ich aus, welches JDK meine Gradle-Builds ausführt?

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

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

Beim Ausführen Ihres Builds erstellt Gradle einen Prozess, der als Daemon bezeichnet wird, um den eigentlichen Build auszuführen. Dieser Prozess kann wiederverwendet werden, solange die Builds dieselbe JDK- und Gradle-Version verwenden. Die Wiederverwendung eines Daemons verkürzt die Zeit zum Starten einer neuen JVM und zum Initialisieren des Build-Systems.

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 vorhandene Gradle JDK-Konfiguration des Projekts ändern möchten, öffnen Sie die Gradle-Einstellungen unter File (oder Android Studio unter macOS) > Settings > Build, Execution, Deployment > 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
  • Ein bestimmtes JDK hinzufügen
  • Lokal erkannte JDKs aus dem JDK-Standardinstallationsverzeichnis des Betriebssystems

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

Abbildung 1: Gradle JDK-Einstellungen in Android Studio

Die Makros ermöglichen die dynamische Auswahl des JDK-Pfads 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 Ihre Gradle-Builds auszuführen und die JDK API-Referenzen beim Bearbeiten Ihrer Build-Skripts und Quellcodes aufzulösen. Die angegebene compileSdk schränkt ein, welche Java-Symbole beim Bearbeiten und Erstellen des Quellcodes verfügbar sind.

Achten Sie darauf, eine JDK-Version auszuwählen, die höher als die oder gleich der JDK-Version ist, die von den Plug-ins verwendet wird, die Sie in Ihrem Gradle-Build verwenden. Die erforderliche JDK-Mindestversion 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 ihn mit einer früheren JDK-Version verwendet, wird eine Meldung wie die folgende angezeigt:

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-Anwendung kann zwar einige, aber nicht alle APIs verwenden, die in einem JDK definiert sind. Im Android SDK werden im Rahmen der verfügbaren APIs die Implementierungen vieler Java-Bibliotheksfunktionen definiert. Das Attribut compileSdk gibt an, welche Android SDK-Version beim Kompilieren des Kotlin- oder Java-Quellcodes verwendet werden soll.

Kotlin

android {
    ...
    compileSdk = 33
}

Groovig

android {
    ...
    compileSdk 33
}

Jede Version von Android 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 im angegebenen minSdk verfügbar ist, können Sie die API möglicherweise in der früheren Android-Version über einen Prozess nutzen, der als Desugaring bezeichnet wird. Unterstützte APIs finden Sie unter Über Desugaring verfügbare Java 11+ APIs.

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 Hauptdienste
13 (API 33) 11 Hauptdienste
12 (API 32) 11 Java API
11 und niedriger Android-Versionen

Welches JDK kompiliert meinen Java-Quellcode?

Das Java Toolchain-JDK enthält den Java-Compiler, der zum Kompilieren des Java-Quellcodes verwendet wird. Dieses JDK führt während des Build-Prozesses auch javadoc- und Unit-Tests aus.

Die Toolchain verwendet standardmäßig das JDK, das zum Ausführen von Gradle verwendet wird. Wenn Sie die Standardversion verwenden und einen Build auf verschiedenen Maschinen 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.

Sie können explizit eine Java-Toolchain-Version angeben, um einen konsistenteren Build zu erstellen. Angabe:

  • Es wird ein kompatibles JDK auf dem System ermittelt, auf dem der Build ausgeführt wird.
    • Wenn kein kompatibles JDK vorhanden und ein Toolchain-Resolver definiert ist, wird ein Download heruntergeladen.
  • Macht die Java-APIs der Toolchain für Aufrufe aus Quellcode verfügbar.
  • Kompiliert die Java-Quelle mit ihrer Java-Sprachversion.
  • Stellt Standardwerte für sourceCompatibility und targetCompatibility bereit.

Sie sollten immer die Java-Toolchain angeben und entweder dafür sorgen, dass das angegebene JDK installiert ist, oder Ihrem Build einen Toolchain-Resolver hinzufügen.

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

Wenn Ihr Quellcode nur in Java geschrieben ist, geben Sie die Java-Toolchain-Version so an:

Kotlin

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

Groovig

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

Wenn Ihre Quelle nur Kotlin oder eine Mischung aus Kotlin und Java ist, geben Sie die Java-Toolchain-Version so an:

Kotlin

kotlin {
    jvmToolchain(17)
}

Groovig

kotlin {
    jvmToolchain 17
}

Die JDK-Version der Toolchain kann mit dem JDK identisch sein, das zur Ausführung von Gradle verwendet wird. Beachten Sie jedoch, dass sie unterschiedlichen Zwecken dienen.

Welche Java-Quellfunktionen 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 wirkt sich nicht auf die Kotlin-Quelle aus.

Wenn keine Angabe erfolgt, wird standardmäßig die Java-Toolchain oder das JDK verwendet, das 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
    }
}

Groovig

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

Welche binären Java-Funktionen können bei der Kompilierung meiner Kotlin- oder Java-Quelle verwendet werden?

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

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

Für targetCompatibility wird standardmäßig der gleiche Wert wie für sourceCompatibility festgelegt. Wenn er jedoch angegeben wird, muss er größer oder gleich sourceCompatibility sein.

jvmTarget ist standardmäßig die Toolchain-Version.

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

Kotlin

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

Groovig

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