Versioni Java nelle build Android

Indipendentemente dal fatto che il codice sorgente sia scritto in Java, Kotlin o entrambi, devi scegliere una versione del JDK o del linguaggio Java per la build in diverse posizioni.

Panoramica delle relazioni JDK in una build Gradle
Figura 1. Relazioni JDK in una build

Glossario

Java Development Kit (JDK)
Java Development Kit (JDK) contiene:
  • Strumenti, come un compilatore, un profiler e un creatore di archivi. Questi vengono utilizzati dietro le quinte durante la build per creare l'applicazione.
  • Librerie contenenti API che puoi chiamare dal tuo codice sorgente Kotlin o Java. Tieni presente che non tutte le funzioni sono disponibili su Android.
  • Java Virtual Machine (JVM), un interprete che esegue le applicazioni Java. Utilizzi la JVM per eseguire l'IDE di Android Studio e lo strumento di build Gradle. La JVM non viene utilizzata su dispositivi o emulatori Android.
JetBrains Runtime (JBR)
JetBrains Runtime (JBR) è un JDK avanzato, distribuito con Android Studio. Include diverse ottimizzazioni per l'utilizzo in Studio e nei prodotti JetBrains correlati, ma può essere utilizzato anche per eseguire altre applicazioni Java.

Come faccio a scegliere un JDK per eseguire Android Studio?

Ti consigliamo di utilizzare JBR per eseguire Android Studio. Viene distribuito con Android Studio e utilizzato per testarlo, oltre a includere miglioramenti per un utilizzo ottimale di Android Studio. Per assicurarti che ciò avvenga, non impostare la variabile di ambiente STUDIO_JDK.

Gli script di avvio di Android Studio cercano una JVM nel seguente ordine:

  1. Variabile di ambiente STUDIO_JDK
  2. Directory studio.jdk (nella distribuzione di Android Studio)
  3. Directory jbr (JetBrains Runtime), nella distribuzione di Android Studio. Consigliata.
  4. Variabile di ambiente JDK_HOME
  5. Variabile di ambiente JAVA_HOME
  6. Eseguibile java nella variabile di ambiente PATH

Come faccio a scegliere il JDK che esegue le mie build Gradle?

Se esegui Gradle utilizzando i pulsanti di Android Studio, per l'esecuzione di Gradle viene utilizzato il JDK impostato nelle impostazioni di Android Studio. Se esegui Gradle in un terminale, all'interno o all'esterno di Android Studio, la variabile di ambiente JAVA_HOME (se impostata) determina quale JDK esegue gli script Gradle. Se JAVA_HOME non è impostato, utilizza il comando java sulla variabile di ambiente PATH.

Per risultati più coerenti, assicurati di impostare la variabile di ambiente JAVA_HOME e la configurazione del JDK Gradle in Android Studio sullo stesso JDK.

Quando esegui la build, Gradle crea un processo chiamato daemon per eseguire la build effettiva. Questo processo può essere riutilizzato, a condizione che le build utilizzino la stessa versione di JDK e Gradle. Il riutilizzo di un daemon riduce il tempo necessario per avviare una nuova JVM e inizializzare il sistema di build.

Se avvii build con JDK o versioni di Gradle diverse, vengono creati daemon aggiuntivi, che consumano più CPU e memoria.

Configurazione del JDK di Gradle in Android Studio

Per modificare la configurazione del JDK Gradle del progetto esistente, apri le impostazioni di Gradle da File (o Android Studio su macOS) > Impostazioni > Build, Execution, Deployment > Build Tools > Gradle. Il menu a discesa JDK Gradle contiene le seguenti opzioni tra cui scegliere:

  • Macro come JAVA_HOME e GRADLE_LOCAL_JAVA_HOME
  • Voci della tabella JDK in formato vendor-version come jbr-17 archiviate nei file di configurazione Android
  • Download di un JDK
  • Aggiunta di un JDK specifico
  • JDK rilevati localmente dalla directory di installazione predefinita del JDK del sistema operativo

L'opzione selezionata viene memorizzata nell'opzione gradleJvm nel file .idea/gradle.xml del progetto e la risoluzione del percorso JDK viene utilizzata per eseguire Gradle quando viene avviato tramite Android Studio.

Figura 2. Impostazioni JDK di Gradle in Android Studio.

Le macro consentono la selezione dinamica del percorso del JDK del progetto:

  • JAVA_HOME: utilizza la variabile di ambiente con lo stesso nome
  • GRADLE_LOCAL_JAVA_HOME: utilizza la proprietà java.home nel file .gradle/config.properties, che per impostazione predefinita è JetBrains Runtime.

Il JDK selezionato viene utilizzato per eseguire la build Gradle e risolvere i riferimenti API JDK durante la modifica degli script di build e del codice sorgente. Tieni presente che il valore compileSdk specificato limiterà ulteriormente i simboli Java disponibili durante la modifica e la creazione del codice sorgente.

Assicurati di scegliere una versione di JDK superiore o uguale alle versioni di JDK utilizzate dai plug-in che utilizzi nella build Gradle. Per determinare la versione minima del JDK richiesta per il plug-in Android per Gradle (AGP), consulta la tabella di compatibilità nelle note di rilascio.

Ad esempio, il plug-in Android per Gradle versione 8.x richiede JDK 17. Se provi a eseguire una build Gradle che lo utilizza con una versione precedente del JDK, viene visualizzato un messaggio simile al seguente:

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

Quali API Java posso utilizzare nel mio codice sorgente Java o Kotlin?

Un'app per Android può utilizzare alcune delle API definite in un JDK, ma non tutte. L'SDK Android definisce le implementazioni di molte funzioni della libreria Java nell'ambito delle sue API disponibili. La proprietà compileSdk specifica quale versione dell'SDK Android utilizzare durante la compilazione del codice sorgente Kotlin o Java.

Kotlin

android {
    ...
    compileSdk = 36
}

Alla moda

android {
    ...
    compileSdk 36
}

Ogni versione di Android supporta una versione specifica del JDK e un sottoinsieme delle sue API Java disponibili. Se utilizzi un'API Java disponibile in un compileSdk non disponibile nella versione minSdk specificata, potresti essere in grado di utilizzare l'API nella versione precedente di Android tramite un processo noto come desugaring. Consulta le API Java 11+ disponibili tramite desugaring per le API supportate.

Utilizza questa tabella per determinare quale versione di Java è supportata da ogni API Android e dove trovare i dettagli sulle API Java disponibili.

Android Java Funzionalità di API e linguaggio supportate
14 (API 34) 17 Librerie principali
13 (API 33) 11 Librerie principali
12 (API 32) 11 API Java
11 e versioni precedenti Versioni di Android

Quale JDK compila il mio codice sorgente Java?

Il JDK della toolchain Java contiene il compilatore Java utilizzato per compilare qualsiasi codice sorgente Java. Questo JDK esegue anche javadoc e test delle unità durante la build.

La toolchain utilizza per impostazione predefinita il JDK utilizzato per eseguire Gradle. Se utilizzi l'impostazione predefinita ed esegui una build su macchine diverse (ad esempio, la tua macchina locale e un server di integrazione continua separato), i risultati della build possono variare se vengono utilizzate versioni di JDK diverse.

Per creare una build più coerente, puoi specificare esplicitamente una versione della toolchain Java. Se specifichi questo:

  • Individua un JDK compatibile sul sistema che esegue la build.
    • Se non esiste un JDK compatibile (e viene definito un resolver della toolchain), ne scarica uno.
  • Espone le API Java della toolchain per le chiamate dal codice sorgente.
  • Compila il codice sorgente Java utilizzando la versione del linguaggio Java.
  • Fornisce i valori predefiniti per sourceCompatibility e targetCompatibility.

Ti consigliamo di specificare sempre la toolchain Java e di assicurarti che il JDK specificato sia installato o di aggiungere un resolver della toolchain alla build.

Puoi specificare la toolchain indipendentemente dal fatto che il codice sorgente sia scritto in Java, Kotlin o entrambi. Specifica la toolchain nel file build.gradle(.kts) di primo livello del modulo.

Specifica la versione della toolchain Java in questo modo:

Kotlin

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

Alla moda

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

Questo funziona se l'origine è Kotlin, Java o una combinazione di entrambi.

La versione del JDK della toolchain può essere la stessa del JDK utilizzato per eseguire Gradle, ma tieni presente che hanno scopi diversi.

Quali funzionalità del linguaggio Java posso utilizzare nel mio codice sorgente Java?

La proprietà sourceCompatibility determina quali funzionalità del linguaggio Java sono disponibili durante la compilazione del codice sorgente Java. Non influisce sul codice sorgente Kotlin.

Specifica sourceCompatibility nel file build.gradle(.kts) del modulo come segue:

Kotlin

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
    }
}

Alla moda

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

Se non specificata, questa proprietà assume per impostazione predefinita la versione della toolchain Java. Se non utilizzi una toolchain Java, per impostazione predefinita viene utilizzata una versione scelta dal plug-in Android per Gradle (ad esempio Java 8 o versioni successive).

Quali funzionalità dei file binari Java posso utilizzare quando compilo il mio codice sorgente Kotlin o Java?

La proprietà targetCompatibility determina la versione del formato della classe Java utilizzata durante la generazione del bytecode per il codice sorgente Java e Kotlin compilato.

Alcune funzionalità di Kotlin esistevano prima dell'aggiunta di funzionalità Java equivalenti. I primi compilatori Kotlin dovevano creare un modo proprio per rappresentare queste funzionalità di Kotlin. Alcune di queste funzionalità sono state successivamente aggiunte a Java. Con i livelli targetCompatibility successivi, il compilatore Kotlin potrebbe utilizzare direttamente la funzionalità Java, il che potrebbe comportare un rendimento migliore.

Versioni diverse di Android supportano versioni diverse di Java. Puoi sfruttare funzionalità Java aggiuntive aumentando targetCompatibility, ma questo potrebbe costringerti ad aumentare anche la versione minima dell'SDK Android per garantire la disponibilità della funzionalità.

Tieni presente che targetCompatibility deve essere maggiore o uguale a sourceCompatibility. In pratica, sourceCompatibility e targetCompatibility dovrebbero generalmente utilizzare lo stesso valore. Puoi impostarli come segue:

Kotlin

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }
}

Alla moda

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
}

Se utilizzi una versione di Kotlin precedente alla 2.2, devi anche impostare kotlinOptions:

Kotlin

android {
    kotlinOptions {
        jvmTarget = "17"
    }
}

Alla moda

android {
    kotlinOptions {
        jvmTarget = "17"
    }
}

Se non specificate, queste proprietà assumono per impostazione predefinita la versione della toolchain Java. Se non utilizzi una toolchain Java, i valori predefiniti potrebbero essere diversi e causare problemi di build. Pertanto, ti consigliamo di specificare sempre questi valori in modo esplicito o di utilizzare una toolchain Java.