Версии Java в сборках Android

Независимо от того, написан ли ваш исходный код на Java, Kotlin или на обоих языках, есть несколько мест, где вы должны выбрать версию JDK или языка Java для своей сборки.

Обзор связей JDK в сборке Gradle
Рисунок 1. JDK в сборке.

Глоссарий

Java Development Kit (JDK)
Java Development Kit (JDK) содержит:
  • Инструменты, такие как компилятор, профилировщик и архиватор. Они используются в фоновом режиме при сборке приложения.
  • Библиотеки, содержащие API, которые можно вызывать из исходного кода Kotlin или Java. Обратите внимание, что на устройствах Android доступны не все функции.
  • Виртуальная машина Java (JVM) – интерпретатор, который выполняет приложения Java. JVM используется для запуска Android Studio IDE и инструмента сборки Gradle. JVM не используется на устройствах и эмуляторах Android.
JetBrains Runtime (JBR)
JetBrains Runtime (JBR)  – это улучшенный JDK, который поставляется вместе с Android Studio. Она включает несколько оптимизаций для использования в Studio и связанных продуктах JetBrains, но также может использоваться для запуска других приложений Java.

Как выбрать JDK для запуска Android Studio?

Мы рекомендуем использовать JBR для запуска Android Studio. Он развертывается вместе с Android Studio и используется для тестирования, а также включает улучшения для оптимального использования Android Studio. Чтобы обеспечить это, не задавайте переменную среды STUDIO_JDK.

Сценарии запуска Android Studio ищут JVM в следующем порядке:

  1. Переменная среды STUDIO_JDK
  2. Каталог studio.jdk (в дистрибутиве Android Studio)
  3. jbr (JetBrains Runtime) в дистрибутиве Android Studio. Рекомендовано.
  4. Переменная среды JDK_HOME
  5. Переменная среды JAVA_HOME
  6. Исполняемый файл java в переменной среды PATH

Как выбрать JDK для сборки Gradle?

Если вы запускаете Gradle с помощью кнопок в Android Studio, для запуска Gradle используется JDK, заданный в настройках Android Studio. Если вы запускаете Gradle в терминале (в Android Studio или вне ее), то, какой JDK будет выполнять скрипты Gradle, определяется переменной среды JAVA_HOME (если она задана). Если переменная JAVA_HOME не задана, используется команда java из переменной среды PATH.

Чтобы обеспечить стабильную работу, укажите этот же JDK в переменной среды JAVA_HOME и конфигурации Gradle JDK в Android Studio.

При запуске сборки Gradle создает процесс, называемый демоном, который выполняет фактическую сборку. Этот процесс можно использовать повторно, если в сборках используются те же версии JDK и Gradle. Повторное использование демона сокращает время, необходимое для запуска новой JVM и инициализации системы сборки.

Если вы запускаете сборки с разными версиями JDK или Gradle, создаются дополнительные демоны, которые потребляют больше ресурсов ЦП и памяти.

Конфигурация Gradle JDK в Android Studio

Чтобы изменить конфигурацию Gradle JDK в существующем проекте, откройте настройки Gradle. Для этого выберите File (Файл) (или Android Studio в macOS) > Settings (Настройки) > Build, Execution, Deployment (Сборка, выполнение, развертывание) > Build Tools (Инструменты сборки) > Gradle. В раскрывающемся списке Gradle JDK доступны следующие варианты:

  • Макросы, например JAVA_HOME и GRADLE_LOCAL_JAVA_HOME.
  • Записи таблицы JDK в формате vendor-version, например jbr-17, которые хранятся в файлах конфигурации Android.
  • Скачивание JDK
  • Добавление определенного JDK
  • JDK, обнаруженные локально в каталоге установки JDK по умолчанию в операционной системе.

Выбранный вариант сохраняется в параметре gradleJvm в файле .idea/gradle.xml проекта, а его путь к JDK используется для запуска Gradle через Android Studio.

Рисунок 2. Настройки Gradle JDK в Android Studio.

Макросы позволяют динамически выбирать путь к JDK проекта:

  • JAVA_HOME – используется переменная среды с тем же названием.
  • GRADLE_LOCAL_JAVA_HOME – использует свойство java.home в файле .gradle/config.properties, которое по умолчанию указывает на JetBrains Runtime.

Выбранный JDK используется для запуска сборки Gradle и разрешения ссылок на API JDK при редактировании скриптов сборки и исходного кода. Обратите внимание, что указанный параметр compileSdk будет дополнительно ограничивать символы Java, доступные при редактировании и сборке исходного кода.

Убедитесь, что вы выбрали версию JDK, которая выше или равна версиям JDK, используемым плагинами в вашей сборке Gradle. Чтобы определить минимальную требуемую версию JDK для плагина Android Gradle (AGP), ознакомьтесь с таблицей совместимости в примечаниях к выпуску.

Например, для плагина Android Gradle версии 8.x требуется JDK 17. Если вы попытаетесь запустить сборку Gradle, которая использует его с более ранней версией JDK, появится сообщение, подобное следующему:

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

Какие Java API можно использовать в исходном коде Java или Kotlin?

Приложение для Android может использовать некоторые API, определенные в JDK, но не все. Android SDK определяет реализации многих функций библиотеки Java как часть доступных API. Свойство compileSdk указывает, какую версию Android SDK использовать при компиляции исходного кода Kotlin или Java.

Kotlin

android {
    ...
    compileSdk = 36
}

Яркий

android {
    ...
    compileSdk 36
}

Каждая версия Android поддерживает определенную версию JDK и подмножество доступных в ней Java API. Если вы используете Java API, доступный в compileSdk, который недоступен в указанном minSdk, вы можете использовать API в более ранней версии Android с помощью процесса, известного как десахаризация. Список поддерживаемых API приведен в статье API Java 11+, доступные через десахаризацию.

В таблице ниже указано, какие версии Java поддерживаются каждым Android API и где найти информацию о доступных Java API.

Android Java Поддерживаемые функции API и языки
14 (API 34) 17 Основные библиотеки
13 (API 33) 11 Основные библиотеки
12 (API 32) 11 Java API
11 и ниже Версии Android

Какой JDK компилирует мой исходный код Java?

Тулчейн Java JDK содержит компилятор Java, который используется для компиляции любого исходного кода Java. Этот JDK также запускает javadoc и модульные тесты во время сборки.

По умолчанию используется JDK, с помощью которого запускается Gradle. Если вы используете версию по умолчанию и запускаете сборку на разных компьютерах (например, на локальном компьютере и отдельном сервере непрерывной интеграции), результаты сборки могут отличаться, если используются разные версии JDK.

Чтобы сборка была более согласованной, вы можете явно указать версию набора инструментов Java. Указав это:

  • Находит совместимый JDK в системе, где выполняется сборка.
    • Если совместимого JDK нет (и определен распознаватель набора инструментов), скачивает его.
  • Предоставляет Java API набора инструментов для вызовов из исходного кода.
  • Компилирует исходный код Java, используя версию языка Java.
  • Задает значения по умолчанию для sourceCompatibility и targetCompatibility.

Рекомендуем всегда указывать тулчейн Java и либо убедиться, что указанный JDK установлен, либо добавить в сборку распознаватель тулчейна.

Вы можете указать тулчейн независимо от того, на каком языке написан исходный код – Java, Kotlin или обоих. Укажите тулчейн на верхнем уровне файла build.gradle(.kts) модуля.

Укажите версию набора инструментов Java следующим образом:

Kotlin

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

Яркий

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

Это работает, если ваш исходный код написан на Kotlin, Java или на обоих языках.

Версия JDK тулчейна может совпадать с версией JDK, используемой для запуска Gradle, но имейте в виду, что они служат разным целям.

Какие функции исходного кода Java можно использовать в исходном коде Java?

Свойство sourceCompatibility определяет, какие функции языка Java доступны во время компиляции исходного кода Java. Это не влияет на исходный код Kotlin.

Укажите sourceCompatibility в файле build.gradle(.kts) модуля следующим образом:

Kotlin

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
    }
}

Яркий

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

Если это свойство не указано, по умолчанию используется версия набора инструментов Java. Если вы не используете тулчейн Java, по умолчанию выбирается версия, заданная плагином Android Gradle (например, Java 8 или более поздняя).

Какие функции двоичного кода Java можно использовать при компиляции исходного кода Kotlin или Java?

Свойство targetCompatibility определяет версию формата класса Java, которая используется при создании байт-кода для скомпилированного исходного кода Java и Kotlin соответственно.

Некоторые функции Kotlin существовали до того, как были добавлены эквивалентные функции Java. Ранним компиляторам Kotlin приходилось создавать собственный способ представления этих функций Kotlin. Некоторые из этих функций позже были добавлены в Java. В более поздних версиях targetCompatibility компилятор Kotlin может напрямую использовать функцию Java, что может повысить производительность.

Разные версии Android поддерживают разные версии Java. Вы можете использовать дополнительные функции Java, увеличив значение targetCompatibility, но в этом случае вам также может потребоваться увеличить минимальную версию Android SDK, чтобы обеспечить доступность функции.

Обратите внимание, что значение targetCompatibility должно быть больше или равно sourceCompatibility. На практике в полях sourceCompatibility и targetCompatibility обычно указывается одно и то же значение. Вы можете задать их следующим образом:

Kotlin

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

Яркий

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

Если вы используете версию Kotlin ниже 2.2, вам также необходимо установить kotlinOptions:

Kotlin

android {
    kotlinOptions {
        jvmTarget = "17"
    }
}

Яркий

android {
    kotlinOptions {
        jvmTarget = "17"
    }
}

Если они не указаны, по умолчанию используется версия набора инструментов Java. Если вы не используете тулчейн Java, значения по умолчанию могут отличаться и вызывать проблемы со сборкой. Поэтому мы рекомендуем всегда явно указывать эти значения или использовать набор инструментов Java.