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

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

Обзор отношений JDK в сборке Gradle

Глоссарий

Комплект разработки Java (JDK)
Комплект разработки Java (JDK) содержит:
  • Инструменты, такие как компилятор, профилировщик и создатель архива. Они используются «за кулисами» во время сборки вашего приложения.
  • Библиотеки, содержащие API, которые вы можете вызывать из исходного кода Kotlin или Java. Обратите внимание, что не все функции доступны на Android.
  • Виртуальная машина Java (JVM) — интерпретатор, выполняющий приложения Java. Вы используете JVM для запуска Android Studio IDE и инструмента сборки Gradle. JVM не используется на устройствах или эмуляторах Android.
Среда выполнения JetBrains (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, переменная среды JAVA_HOME (если она установлена) определяет, какой JDK запускает сценарии Gradle. Если JAVA_HOME не установлен, он использует команду java для переменной среды PATH .

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

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

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

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

Чтобы изменить конфигурацию Gradle JDK существующего проекта, откройте настройки Gradle в меню «Файл» (или Android Studio в macOS) > «Настройки» > «Сборка, выполнение, развертывание» > «Инструменты сборки» > 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.

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

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

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

Выбранный 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/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`.

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

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

Котлин

android {
    ...
    compileSdk = 33
}

классный

android {
    ...
    compileSdk 33
}

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

Используйте эту таблицу, чтобы определить, какая версия Java поддерживается каждым API Android, а также где найти сведения о доступных API 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 не существует (и определен преобразователь цепочки инструментов), загружается его.
  • Предоставляет API-интерфейсы Java инструментальной цепочки для вызовов из исходного кода.
  • Компилирует исходный код Java, используя его языковую версию Java.
  • Предоставляет значения по умолчанию для sourceCompatibility и targetCompatibility .

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

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

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

Котлин

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

классный

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

Это работает, если вашим источником является Kotlin, Java или их смесь.

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

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

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

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

Укажите sourceCompatibility в файле build.gradle(.kts) вашего модуля.

Котлин

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
    }
}

классный

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

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

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

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

targetCompatibility по умолчанию имеет то же значение, что и sourceCompatibility , но если оно указано, оно должно быть больше или равно sourceCompatibility .

jvmTarget по умолчанию использует версию набора инструментов .

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

Котлин

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

классный

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