d8

d8 — это инструмент командной строки, который Android Studio и плагин Android Gradle используют для компиляции байт-кода Java вашего проекта в байт-код DEX, который работает на устройствах Android. d8 позволяет использовать функции языка Java 8 в коде вашего приложения.

d8 также включен как отдельный инструмент в Android Build Tools 28.0.1 и более поздних версий: android_sdk /build-tools/ version / .

Общее использование

d8 требует только путь к скомпилированному байт-коду Java, который вы хотите преобразовать в байт-код DEX. Например:

d8 MyProject/app/build/intermediates/classes/debug/*/*.class

Входной байт-код может представлять собой любую комбинацию файлов или контейнеров *.class , например файлов JAR, APK или ZIP. Вы также можете включить файлы DEX для d8 для объединения с выходными данными DEX, что полезно при включении выходных данных инкрементной сборки.

По умолчанию d8 компилирует байт-код Java в оптимизированные файлы DEX и включает отладочную информацию, которую вы можете использовать для отладки кода во время выполнения. Однако вы можете включить дополнительные флаги для выполнения инкрементной сборки, указать классы, которые должны быть скомпилированы в основной файл DEX, и указать пути к дополнительным ресурсам, необходимым для использования функций языка Java 8.

d8 path-to-input-files [options]

В следующей таблице описаны дополнительные флаги, которые вы можете использовать с d8 :

Вариант Описание
--debug

Скомпилируйте байт-код DEX, чтобы включить отладочную информацию, например таблицы символов отладки.

Эта опция включена по умолчанию. Чтобы включить отладочную информацию в байт-код DEX, d8 ожидает, что входной байт-код Java включает эту информацию. Например, если вы используете javac для компиляции кода, вам необходимо передать флаг -g , чтобы включить отладочную информацию в выходной байт-код Java.

При компиляции файлов DEX для релизной версии вашего приложения или библиотеки вместо этого используйте флаг --release .

--release

Скомпилируйте байт-код DEX без отладочной информации. Однако d8 включает некоторую информацию, которая используется при создании трассировок стека и регистрации исключений.

Передайте этот флаг при компиляции байт-кода для публичного выпуска.

--output path

Укажите желаемый путь для вывода DEX. По умолчанию d8 выводит файлы DEX в текущем рабочем каталоге.

Если вы укажете путь и имя файла ZIP или JAR, d8 создаст указанный файл и включит выходные файлы DEX. Если вы укажете путь к существующему каталогу, d8 выведет файлы DEX в этом каталоге.

--lib android_sdk /platforms/ api-level /android.jar Укажите путь к android.jar вашего Android SDK. Этот флаг необходим при компиляции байт-кода, использующего возможности языка Java 8 .
--classpath path Укажите ресурсы пути к классам, которые могут потребоваться d8 для компиляции файлов DEX вашего проекта. В частности, d8 требует, чтобы вы указали определенные ресурсы при компиляции байт-кода, использующего возможности языка Java 8 .
--min-api number Укажите минимальный уровень API, который должны поддерживать выходные файлы DEX.
--intermediate Передайте этот флаг, чтобы сообщить d8 , что вы не компилируете полный набор байт-кода Java вашего проекта. Этот флаг полезен при выполнении инкрементных сборок. Вместо компиляции оптимизированных файлов DEX, которые вы ожидаете запустить на устройстве, d8 создает промежуточные файлы DEX и сохраняет их в указанном выходном или пути по умолчанию.

Если вы хотите скомпилировать файлы DEX, которые собираетесь запускать на устройстве, исключите этот флаг и укажите путь к промежуточным классам DEX в качестве входных данных.

--file-per-class

Скомпилируйте каждый класс в отдельные файлы DEX.

Включение этого флага позволяет выполнять дополнительные инкрементные сборки, перекомпилируя только те классы, которые изменились. При выполнении инкрементных сборок с использованием плагина Android Gradle эта оптимизация включена по умолчанию.

Вы не можете использовать этот флаг, одновременно указав --main-dex-list .

--no-desugaring Отключите функции языка Java 8. Используйте этот флаг только в том случае, если вы не собираетесь компилировать байт-код Java, использующий функции языка Java 8.
--main-dex-list path

Укажите текстовый файл, в котором перечислены классы d8 которые следует включить в основной файл DEX, который обычно classes.dex . Если вы не указываете список классов, используя этот флаг, d8 не гарантирует, какие классы включены в основной файл DEX.

Поскольку система Android при запуске приложения сначала загружает основной файл DEX, вы можете использовать этот флаг для определения приоритета определенных классов при запуске, компилируя их в основной файл DEX. Это особенно полезно при поддержке устаревшей мультидексной библиотеки, поскольку во время выполнения доступны только классы в основном файле DEX, пока не будет загружена устаревшая мультидексная библиотека.

Имейте в виду, что каждый файл DEX по-прежнему должен соответствовать эталонному пределу в 64 КБ . Поэтому не указывайте слишком много классов для основного файла DEX, иначе вы получите ошибку компиляции. По умолчанию при указании классов с помощью --main-dex-list d8 включает только эти классы в основной файл DEX. Это сделано для того, чтобы упростить отладку проблем, связанных с отсутствием классов в основном файле DEX. Если вы укажете режим --release , d8 попытается уменьшить количество файлов DEX, упакованных в релизную версию вашего приложения, включая как можно больше других классов в основной файл DEX, пока не будет достигнут предел в 64 КБ.

Вы не можете использовать этот флаг, одновременно указав --file-per-class .

--pg-map file Используйте file в качестве файла сопоставления для распространения.
--file-per-class-file

Создайте отдельный файл DEX для каждого входного файла .class.

Сохраняйте синтетические классы вместе с исходным классом.

--desugared-lib file

Укажите конфигурацию библиотеки без сахара.

file представляет собой очищенный файл конфигурации библиотеки в формате JSON.

--main-dex-rules file Proguard сохраняет правила размещения классов в основном файле DEX.
--main-dex-list-output file Выведите результирующий основной список DEX в файл .

--force-enable-assertions [: class_or_package_name ...]

--force-ea [: class_or_package_name ...]

Принудительно включить код утверждения, сгенерированный javac .

--force-disable-assertions [: class_or_package_name ...]

--force-da [: class_or_package_name ...]

Принудительно отключить код утверждения, сгенерированный javac . Это обработка кода утверждения javac по умолчанию при создании файлов DEX.

--force-passthrough-assertions [: class_or_package_name ...]

--force-pa [: class_or_package_name ...]

Не изменяйте код утверждения, сгенерированный javac . Это обработка кода утверждения javac по умолчанию при создании файлов class .

--force-assertions-handler: handler method [: class_or_package_name ...]

--force-ah: handler method [: class_or_package_name ...]

Измените код утверждения, сгенерированный javac и kotlinc , чтобы вызывать handler method метода при каждой ошибке утверждения, а не выдавать его. handler method указывается как имя класса, за которым следует точка и имя метода. Метод-обработчик должен принимать один аргумент типа java.lang.Throwable и возвращать тип void .
--thread-count number of threads Укажите количество потоков, которые будут использоваться для компиляции. Если не указано, число основано на эвристике с учетом количества ядер.
--map-diagnostics[ : type ] from-level to-level Диагностика карты type (по умолчанию любой), сообщаемая как from-level to to-level , где from-level и to-level — это «информация», «предупреждение» или «ошибка», а необязательный type — простой или полное имя типа Java диагностики. Если type не указан, сопоставляются все диагностики на from-level . Обратите внимание, что фатальные ошибки компилятора не могут быть отображены.
--version Распечатайте версию d8 , которую вы сейчас используете.
--help Распечатать текст справки по использованию d8 .

Выполнение дополнительных сборок

Чтобы повысить скорость сборки во время разработки, например, для сборок непрерывной интеграции, попросите d8 скомпилировать только подмножество байт-кода Java вашего проекта. Например, если вы включите индексирование для каждого класса, вы сможете перекомпилировать только те классы, которые вы изменили с момента предыдущей сборки.

Следующая команда выполняет инкрементную сборку нескольких классов и включает индексацию для каждого класса. Команда также указывает выходной каталог для инкрементной сборки.

d8 MainActivity.class R.class --intermediate --file-per-class --output ~/build/intermediate/dex

Когда d8 выполняет инкрементную сборку, он сохраняет дополнительную информацию в выходных данных DEX. Позже d8 использует эту информацию для правильной обработки параметра --main-dex-list и объединения файлов DEX во время полной сборки вашего приложения.

Например, при обработке лямбда-классов Java 8 d8 отслеживает, какие лямбда-классы созданы для каждого входного класса. Во время полной сборки, когда d8 включает класс в основной файл DEX, он проверяет метаданные, чтобы убедиться, что все лямбда-классы, созданные для этого класса, также включены в основной файл DEX.

Если вы уже скомпилировали весь байт-код вашего проекта в файлы DEX в нескольких инкрементных сборках, выполните полную сборку, передав каталог промежуточных файлов DEX в d8 , как показано в следующей команде. Кроме того, вы можете указать классы, которые d8 должен скомпилировать в основной файл DEX, используя --main-dex-list . Поскольку входные данные представляют собой набор файлов, которые уже скомпилированы в байт-код DEX, эта сборка должна завершиться быстрее, чем чистая сборка.

d8 ~/build/intermediate/dex --release --main-dex-list ~/build/classes.txt --output ~/build/release/dex

Скомпилируйте байт-код, использующий функции языка Java 8.

d8 позволяет вам использовать функции языка Java 8 в вашем коде посредством процесса компиляции, называемого desugaring . Desugaring преобразует эти полезные функции языка в байт-код, который может работать на платформе Android.

Android Studio и плагин Android Gradle включают ресурсы пути к классам, которые необходимы d8 для включения удаления сахара. Однако при использовании d8 из командной строки вам необходимо включить их самостоятельно.

Одним из таких ресурсов является android.jar из целевого Android SDK. Этот ресурс включает набор API-интерфейсов платформы Android. Укажите его путь, используя флаг --lib .

Другим ресурсом является набор байт-кода Java, скомпилированный в ваш проект, который вы в настоящее время не компилируете в байт-код DEX, но который требуется для компиляции других классов в байт-код DEX.

Например, если ваш код использует методы интерфейса по умолчанию и статические методы интерфейса , которые являются особенностью языка Java 8, вам необходимо использовать этот флаг, чтобы указать путь ко всему байт-коду Java вашего проекта, даже если вы не собираетесь компилировать все байт-код в байт-код DEX. Это потому, что d8 требует этой информации для понимания кода вашего проекта и разрешения вызовов методов интерфейса.

В следующем примере кода выполняется инкрементальная сборка класса, который обращается к методу интерфейса по умолчанию:

d8 MainActivity.class --intermediate --file-per-class --output ~/build/intermediate/dex
--lib android_sdk/platforms/api-level/android.jar
--classpath ~/build/javac/debug