Wersje Javy w kompilacjach Androida

Niezależnie od tego, czy kod źródłowy jest napisany w Javie, w Kotlinie czy w obu tych językach, musisz wybrać dla swojej kompilacji wersję JDK lub Java w kilku miejscach.

Omówienie relacji JDK w kompilacji Gradle

Słowniczek

Pakiet Java Development Kit (JDK)
Pakiet Java Development Kit (JDK) zawiera:
  • narzędzia, takie jak kompilator, profiler i twórca archiwów; Są one używane w tle podczas kompilacji podczas tworzenia aplikacji.
  • Biblioteki zawierające interfejsy API, które można wywoływać z kodu źródłowego Kotlin lub Java. Pamiętaj, że nie wszystkie funkcje są dostępne na Androidzie.
  • Maszyna wirtualna Java (JVM) – interpreter interpretujący aplikacje w Javie. Do uruchamiania środowiska Android Studio IDE i narzędzia do kompilacji Gradle używasz maszyny JVM. Nie można jej używać na urządzeniach z Androidem ani w emulatorach.
Środowisko wykonawcze JetBrains (JBR)
JetBrains Runtime (JBR) to ulepszony pakiet JDK rozpowszechniany w Android Studio. Zawiera kilka optymalizacji do wykorzystania w Studio i powiązanych usługach JetBrains, ale można go też używać do uruchamiania innych aplikacji w Javie.

Jak wybrać pakiet JDK do uruchamiania Android Studio?

Do uruchamiania Android Studio zalecamy używanie JBR. Jest wdrażany wraz z Androidem Studio i używany do jego testowania. Zawiera też ulepszenia pozwalające na optymalne wykorzystanie tego środowiska. Aby mieć pewność, że tak się stanie, nie ustawiaj zmiennej środowiskowej STUDIO_JDK.

Skrypty startowe Android Studio szukają JVM w tej kolejności:

  1. STUDIO_JDK zmienna środowiskowa
  2. Katalog studio.jdk (w dystrybucji Android Studio)
  3. jbr (środowisko wykonawcze JetBrains) w dystrybucji Android Studio. Zalecane.
  4. JDK_HOME zmienna środowiskowa
  5. JAVA_HOME zmienna środowiskowa
  6. Plik wykonywalny java w zmiennej środowiskowej PATH

Jak wybrać pakiet JDK uruchamiający moje kompilacje Gradle?

Jeśli uruchamiasz Gradle za pomocą przycisków w Android Studio, do jego uruchamiania używany jest pakiet JDK ustawiony w ustawieniach Android Studio. Jeśli uruchomisz Gradle w terminalu, w Android Studio lub poza nim, zmienna środowiskowa JAVA_HOME (jeśli jest ustawiona) określa, który pakiet JDK uruchamia skrypty Gradle. Jeśli zasada JAVA_HOME jest nieskonfigurowana, używa polecenia java w zmiennej środowiskowej PATH.

Aby uzyskać najbardziej spójne wyniki, ustaw tę samą zmienną środowiskową JAVA_HOME i konfigurację Gradle JDK w Android Studio na ten sam pakiet JDK.

Podczas uruchamiania kompilacji Gradle tworzy proces nazywany daemonem, który wykonuje rzeczywistą kompilację. Tego procesu można użyć ponownie, o ile kompilacje korzystają z tej samej wersji pakietu JDK i Gradle. Ponowne użycie demona skraca czas uruchamiania nowej maszyny JVM i zainicjowania systemu kompilacji.

Jeśli rozpoczniesz kompilacje z różnymi wersjami pakietu JDK lub Gradle, zostaną utworzone dodatkowe demony, które zużywają więcej CPU i pamięci.

Konfiguracja Gradle JDK w Android Studio

Aby zmodyfikować konfigurację Gradle JDK w istniejącym projekcie, otwórz ustawienia Gradle, klikając Plik (lub Android Studio w systemie macOS) > Ustawienia > Kompilacja, Wykonywanie, Wdrożenie > Narzędzia do kompilacji > Gradle. Menu Gradle JDK zawiera następujące opcje do wyboru:

  • Makra, np. JAVA_HOME i GRADLE_LOCAL_JAVA_HOME
  • Wpisy w tabeli JDK w formacie vendor-version, np. jbr-17, które są przechowywane w plikach konfiguracji Androida
  • Pobieranie pakietu JDK
  • Dodawanie określonego pakietu JDK
  • Pliki JDK wykryte lokalnie w domyślnym katalogu instalacyjnym pakietu JDK systemu operacyjnego

Wybrana opcja jest przechowywana w opcji gradleJvm w pliku .idea/gradle.xml projektu, a rozdzielczość ścieżki JDK jest używana do uruchamiania Gradle w przypadku uruchamiania w Android Studio.

Rysunek 1. Ustawienia Gradle JDK w Android Studio.

Te makra umożliwiają wybór ścieżki JDK w projekcie dynamicznym:

  • JAVA_HOME: używa zmiennej środowiskowej o tej samej nazwie
  • GRADLE_LOCAL_JAVA_HOME: używa właściwości java.home w pliku .gradle/config.properties, którego domyślne ustawienie to środowisko wykonawcze JetBrains.

Wybrany pakiet JDK służy do uruchamiania kompilacji Gradle i rozwiązywania odwołań do interfejsu JDK API podczas edytowania skryptów kompilacji i kodu źródłowego. Pamiętaj, że podany compileSdk jeszcze bardziej ogranicza dostępność symboli Javy podczas edytowania i tworzenia kodu źródłowego.

Wybierz wersję JDK wyższą lub równą wersji JDK używanych przez wtyczki używane w kompilacji Gradle. Aby określić minimalną wymaganą wersję JDK dla wtyczki Android do obsługi Gradle (AGP), zajrzyj do tabeli zgodności w informacjach o wersji.

Na przykład wtyczka Androida do obsługi Gradle w wersji 8.x wymaga pakietu JDK 17. Jeśli spróbujesz uruchomić kompilację Gradle, która używa jej z wcześniejszą wersją pakietu JDK, otrzymasz komunikat podobny do tego:

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

Których interfejsów API w Javie mogę używać w kodzie źródłowym Java lub Kotlin?

Aplikacja na Androida może używać niektórych interfejsów API zdefiniowanych w JDK, ale nie wszystkich. Pakiet Android SDK definiuje implementacje wielu funkcji biblioteki Java w ramach dostępnych interfejsów API. Właściwość compileSdk określa, której wersji pakietu SDK na Androida należy użyć podczas kompilowania kodu źródłowego Kotlin lub Java.

Kotlin

android {
    ...
    compileSdk = 33
}

Odlotowe

android {
    ...
    compileSdk 33
}

Każda wersja Androida obsługuje konkretną wersję JDK i podzbiór dostępnych w niej interfejsów API Java. Jeśli używasz interfejsu API Java, który jest dostępny w compileSdk, który nie jest dostępny w podanym minSdk, może być możliwe użycie interfejsu API we wcześniejszej wersji Androida w ramach procesu zwanego desugaring. Listę obsługiwanych interfejsów API znajdziesz w artykule o interfejsach API w języku Java 11+ dostępnych w ramach desugaringu.

Z tej tabeli dowiesz się, która wersja Javy jest obsługiwana przez poszczególne interfejsy API Androida oraz gdzie znaleźć szczegółowe informacje na temat dostępnych interfejsów API Java.

Android Java Obsługiwane funkcje interfejsu API i języków
14 (API 34) 17 Biblioteki podstawowe
13 (API 33) 11 Biblioteki podstawowe
12 (API 32) 11 Interfejs Java API
11 i mniej Wersje Androida

Który pakiet JDK kompiluje mój kod źródłowy w Javie?

Plik JDK Java toolchain zawiera kompilator Java używany do skompilowania kodu źródłowego w Javie. Ten pakiet JDK uruchamia także testy javadoc i testy jednostkowe podczas kompilacji.

Domyślnym łańcuchem narzędzi jest pakiet JDK użyty do uruchomienia Gradle. Jeśli użyjesz ustawień domyślnych i uruchomisz kompilację na różnych komputerach (na przykład na komputerze lokalnym i na osobnym serwerze ciągłej integracji), wyniki kompilacji mogą się różnić w przypadku użycia różnych wersji pakietu JDK.

Aby utworzyć bardziej spójną kompilację, możesz jawnie określić wersję łańcucha narzędzi Java. Określenie:

  • Lokalizuje zgodny pakiet JDK w systemie, w którym uruchamiana jest kompilacja.
    • Jeśli nie istnieje zgodny pakiet JDK (i został zdefiniowany resolver łańcucha narzędzi), pobiera go.
  • Udostępnia interfejsy API w Javie dla łańcucha narzędzi dla wywołań kodu źródłowego.
  • Kompiluje źródło w Javie z użyciem jej wersji językowej.
  • Domyślne ustawienia zasobów reklamowych w przypadku sourceCompatibility i targetCompatibility.

Zalecamy, aby zawsze wskazywać łańcuch narzędzi Java i upewnić się, że określony pakiet JDK jest zainstalowany lub dodać do kompilacji mechanizm resolverowy.

Łańcuch narzędzi możesz określić w przypadku tego, czy Twój kod źródłowy jest napisany w języku Java, Kotlin czy w obu tych językach. Określ łańcuch narzędzi na najwyższym poziomie pliku build.gradle(.kts) modułu.

Określ wersję łańcucha narzędzi Java w ten sposób:

Kotlin

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

Odlotowe

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

Sprawdza się to, jeśli źródłem jest Kotlin lub Java albo ich kombinacja.

Wersja łańcucha narzędzi JDK może być taka sama jak pakiet JDK używany do uruchamiania Gradle, ale pamiętaj, że służą one do różnych celów.

Których funkcji źródłowych języka Java mogę używać w moim kodzie źródłowym Java?

Właściwość sourceCompatibility określa, które funkcje języka Java są dostępne podczas kompilacji źródła w języku Java. Nie ma wpływu na źródło Kotlin.

Jeśli nie podasz żadnej wartości, domyślnie będzie używany łańcuch narzędzi Java lub pakiet JDK używany do uruchamiania Gradle. Zalecamy, aby zawsze bezpośrednio określać łańcuch narzędzi (preferowane) lub sourceCompatibility.

Określ sourceCompatibility w pliku build.gradle(.kts) modułu.

Kotlin

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
    }
}

Odlotowe

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

Jakich funkcji binarnych w Javie można używać podczas skompilowania kodu źródłowego w języku Kotlin lub Javy?

Określenie targetCompatibility i jvmTarget określa wersję formatu klasy Java używaną odpowiednio do generowania kodu bajtowego odpowiednio dla skompilowanego źródła Java i Kotlin.

Niektóre funkcje Kotlin istniały przed dodaniem równoważnych funkcji w Javie. Wczesne kompilatory Kotlin musiały opracować własny sposób przedstawienia tych cech Kotlin. Niektóre z tych funkcji zostały później dodane do Javy. W przypadku późniejszych poziomów jvmTarget kompilator Kotlin może bezpośrednio korzystać z funkcji Java, co może zwiększyć wydajność.

targetCompatibility domyślnie przyjmuje tę samą wartość co sourceCompatibility, ale jeśli została określona, musi być większa lub równa sourceCompatibility.

jvmTarget domyślnie używa wersji toolchain.

Różne wersje Androida obsługują różne wersje języka Java. Aby skorzystać z dodatkowych funkcji Javy, zwiększ targetCompatibility i jvmTarget. Może to jednak wymagać także zwiększenia minimalnej wersji pakietu Android SDK, aby zapewnić ich dostępność.

Kotlin

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

Odlotowe

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