d8

d8 to narzędzie wiersza poleceń używane przez Android Studio i wtyczkę Androida do obsługi Gradle do skompilowania kodu bajtowego Java Twojego projektu w kod DEX, który działa na urządzeniach z Androidem. d8 umożliwia użycie w kodzie aplikacji funkcji języka Java 8.

Narzędzie d8 jest też dostępne jako samodzielne narzędzie w Android Build Tools w wersji 28.0.1 i nowszych: android_sdk/build-tools/version/.

Zastosowania ogólne

d8 wymaga tylko ścieżki do skompilowanego kodu bajtowego Java, który chcesz przekonwertować na kod DEX. Na przykład:

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

Wejściowy kod bajtowy może mieć dowolną kombinację plików lub kontenerów *.class, np. plików JAR, APK lub ZIP. Możesz też dołączyć pliki DEX dla d8, aby scalać je w dane wyjściowe DEX, co jest przydatne podczas uwzględniania danych wyjściowych z kompilacji przyrostowej.

Domyślnie d8 kompiluje kod bajtowy Javy w zoptymalizowane pliki DEX i zawiera informacje debugowania, które możesz wykorzystać do debugowania kodu w czasie działania. Możesz jednak dołączyć opcjonalne flagi, aby wykonać kompilację przyrostową, określić klasy, które powinny być skompilowane w głównym pliku DEX, i określić ścieżki do dodatkowych zasobów wymaganych do korzystania z funkcji w języku Java 8.

d8 path-to-input-files [options]

W tej tabeli opisujemy opcjonalne flagi, których możesz używać z d8:

Opcja Opis
--debug

Skompiluj kod bajtowy DEX, aby uwzględnić informacje na potrzeby debugowania, takie jak tabele z symbolami debugowania.

Ta opcja jest domyślnie włączona. Aby uwzględnić informacje na potrzeby debugowania w kodzie bajtowym DEX, d8 wymaga, aby podany kod bajtowy Javy zawierał te informacje. Jeśli na przykład do kompilowania kodu używasz polecenia javac, musisz przekazać flagę -g, aby w wyjściowym kodzie bajtowym Javy uwzględnić informacje debugowania.

Podczas kompilowania plików DEX dla wersji aplikacji lub biblioteki używaj flagi --release.

--release

Kompilacja kodu bajtowego DEX bez danych debugowania. d8 zawiera jednak pewne informacje, które są używane podczas generowania zrzutów stosu i wyjątków logowania.

Przekaż tę flagę podczas kompilowania kodu bajtowego wersji publicznej.

--output path

Podaj odpowiednią ścieżkę dla danych wyjściowych DEX. Domyślnie d8 przesyła pliki DEX w bieżącym katalogu roboczym.

Jeśli podasz ścieżkę i nazwę pliku ZIP lub JAR, d8 utworzy określony plik i doda wyjściowe pliki DEX. Jeśli podasz ścieżkę do istniejącego katalogu, d8 wyświetli pliki DEX z tego katalogu.

--lib android_sdk/platforms/api-level/android.jar Podaj ścieżkę do pliku android.jar swojego pakietu Android SDK. Ta flaga jest wymagana podczas kompilacji kodu bajtowego korzystającego z funkcji języka Java 8.
--classpath path Określ zasoby ścieżki klasy, których d8 może potrzebować do skompilowania plików DEX projektu. W szczególności d8 wymaga określenia określonych zasobów podczas kompilacji kodu bajtowego z użyciem funkcji języka Java 8.
--min-api number Określ minimalny poziom interfejsu API, który mają obsługiwać wyjściowe pliki DEX.
--intermediate Przekaż tę flagę, aby poinformować d8, że nie kompilujesz pełnego zestawu kodu bajtowego Java Twojego projektu. Ta flaga jest przydatna podczas wykonywania kompilacji przyrostowych. Zamiast kompilować zoptymalizowane pliki DEX, które powinny być uruchamiane na urządzeniu, d8 tworzy pośrednie pliki DEX i przechowuje je w określonej ścieżce wyjściowej lub domyślnej.

Jeśli chcesz skompilować pliki DEX, które chcesz uruchomić na urządzeniu, wyklucz tę flagę i podaj ścieżkę do pośrednich klas DEX.

--file-per-class

Skompiluj poszczególne klasy w osobne pliki DEX.

Włączenie tej flagi umożliwia wykonywanie większej liczby kompilacji przyrostowych przez ponowne kompilowanie tylko tych klas, które uległy zmianie. Podczas wykonywania kompilacji przyrostowych za pomocą wtyczki Androida do obsługi Gradle ta optymalizacja jest domyślnie włączona.

Nie możesz użyć tej flagi, podając też właściwość --main-dex-list.

--no-desugaring Wyłącz funkcje języka Java 8. Użyj tej flagi tylko wtedy, gdy nie chcesz kompilować kodu bajtowego Java, który korzysta z funkcji języka Java 8.
--main-dex-list path

Określ plik tekstowy z listą klas, które d8 powinna zawierać w głównym pliku DEX. Zwykle ma on nazwę classes.dex. Jeśli nie określisz listy klas za pomocą tej flagi, d8 nie gwarantuje, które klasy zostaną uwzględnione w głównym pliku DEX.

System Android najpierw wczytuje główny plik DEX przy uruchamianiu aplikacji, dlatego możesz użyć tej flagi, aby nadać priorytet określonym klasom podczas uruchamiania, skompilując je w głównym pliku DEX. Jest to szczególnie przydatne w przypadku obsługi starszej wersji biblioteki multidex, ponieważ do momentu załadowania starszej biblioteki multidex w środowisku wykonawczym dostępne są tylko klasy z głównego pliku DEX.

Pamiętaj, że każdy plik DEX musi spełniać limit 64 tys. plików referencyjnych. Nie określaj więc zbyt wielu klas w głównym pliku DEX, bo inaczej wystąpi błąd kompilacji. Domyślnie przy określaniu klas z wykorzystaniem klasy --main-dex-list d8 uwzględnia tylko te klasy w głównym pliku DEX. Ułatwia to debugowanie problemów związanych z klasami, których brakuje w głównym pliku DEX. Jeśli wybierzesz tryb --release, d8 spróbuje zmniejszyć liczbę plików DEX spakowanych do wersji Twojej aplikacji, uwzględniając jak najwięcej innych klas w głównym pliku DEX, aż do osiągnięcia limitu 64 tys.

Nie możesz użyć tej flagi, podając też właściwość --file-per-class.

--pg-map file Użyj file jako pliku mapowania do dystrybucji.
--file-per-class-file

Generuj oddzielny plik DEX na każdy wejściowy plik .class.

Zachowaj klasy syntetyczne z ich klasą początkową.

--desugared-lib file

Określ wykorzystywaną konfigurację biblioteki.

file to wycofywany plik konfiguracji biblioteki w formacie JSON.

--main-dex-rules file ProGuard przechowuje reguły klas, które należy umieścić w głównym pliku DEX.
--main-dex-list-output file Dane wyjściowe wynikowej głównej listy plików DEX w pliku file.

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

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

Wymuszone włączenie kodu asercji wygenerowanego przez javac.

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

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

Wymuś wyłączenie kodu asercji wygenerowanego przez javac. To jest domyślna obsługa kodu asercji javac podczas generowania plików DEX.

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

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

Nie zmieniaj kodu asercji wygenerowanego przez javac. To jest domyślna obsługa kodu asercji javac podczas generowania plików class.

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

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

Zmień kod asercji wygenerowany przez javac i kotlinc, aby zamiast go wywoływać metodę handler method z każdym błędem asercji. handler method jest podawanym jako nazwa klasy, po której następuje kropka i nazwa metody. Metoda obsługi musi przyjmować pojedynczy argument typu java.lang.Throwable i zwracać typ void.
--thread-count number of threads Podaj liczbę wątków, które mają być używane na potrzeby kompilacji. Jeśli nie podasz żadnej wartości, zostanie ona określona na podstawie danych heurystycznych z uwzględnieniem liczby rdzeni.
--map-diagnostics[ :type] from-level to-level Diagnostyka map type (domyślna) zgłoszona jako from-level do to-level, gdzie from-level i to-level to „info”, „ostrzeżenie” lub „błąd”, a opcjonalny type to prosta lub w pełni kwalifikowana nazwa typu Java na potrzeby diagnostyki. Jeśli type nie jest określony, zmapowane są wszystkie dane diagnostyczne w from-level. Pamiętaj, że krytycznych błędów kompilatora nie można zmapować.
--version Wydrukuj wersję programu d8, której aktualnie używasz.
--help Drukuj tekst pomocy dotyczącej używania d8.

Kompilacje przyrostowe

Aby przyspieszyć kompilację podczas programowania, na przykład w przypadku kompilacji w trybie ciągłej integracji, ustaw w d8 kompilowanie tylko części kodu bajtowego Java Twojego projektu. Jeśli na przykład włączysz dexing według klas, możesz skompilować tylko te klasy, które zostały zmodyfikowane od czasu poprzedniej kompilacji.

Poniższe polecenie wykonuje przyrostową kompilację z użyciem kilku klas i umożliwia dexing w poszczególnych klasach. To polecenie określa też katalog wyjściowy dla kompilacji przyrostowej.

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

Gdy d8 wykonuje kompilację przyrostową, zapisuje dodatkowe informacje w danych wyjściowych DEX. d8 później wykorzystuje te informacje do prawidłowego przetwarzania opcji --main-dex-list i scalania plików DEX podczas pełnej kompilacji aplikacji.

Na przykład podczas przetwarzania klas lambda w języku Java 8 d8 śledzi, które klasy są tworzone dla poszczególnych klas wejściowych. Gdy d8 zawiera klasę w głównym pliku DEX, podczas pełnej kompilacji sprawdza metadane, aby mieć pewność, że wszystkie klasy lambda utworzone dla tej klasy są też uwzględnione w głównym pliku DEX.

Jeśli kod bajtowy Twojego projektu jest już skompilowany w pliki DEX w kilku kompilacjach przyrostowych, wykonaj pełną kompilację, przekazując do pliku d8 katalog pośrednich plików DEX, jak pokazano w poniższym poleceniu. Dodatkowo za pomocą --main-dex-list możesz wskazać klasy, które d8 ma skompilować do głównego pliku DEX. Dane wejściowe to zbiór plików, które zostały już skompilowane w kod bajtowy DEX, dlatego ta kompilacja powinna zakończyć się szybciej niż czysta.

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

Kompilacja kodu bajtowego z wykorzystaniem funkcji języka Java 8

d8 umożliwia używanie funkcji językowych Java 8 w kodzie za pomocą procesu kompilacji o nazwie deugaring. Ta funkcja konwertuje przydatne funkcje językowe na kod bajtowy, który działa na platformie Androida.

Android Studio i wtyczka Androida do obsługi Gradle zawierają zasoby ścieżki klasy, których d8 wymaga, aby umożliwić wyłączenie tej funkcji. Jeśli jednak używasz polecenia d8 z poziomu wiersza poleceń, musisz je uwzględnić samodzielnie.

Jednym z takich zasobów jest android.jar z docelowego pakietu SDK do Androida. Ten zasób zawiera zestaw interfejsów API platform Android. Określ jego ścieżkę za pomocą flagi --lib.

Innym zasobem jest zestaw kodu bajtowego Java wkompilowany w Twój projekt, którego obecnie nie skompilujesz do kodu bajtowego DEX, ale musisz skompilować inne klasy do tego kodu.

Na przykład jeśli w Twoim kodzie są używane domyślne i statyczne metody interfejsu, które są funkcją języka Java 8, musisz użyć tej flagi, aby określić ścieżkę do całego kodu bajtowego Java Twojego projektu, nawet jeśli nie zamierzasz kompilować całego kodu w kod bajtowy DEX. Wynika to z faktu, że d8 wymaga tych informacji, aby rozumieć kod projektu i wykonywać wywołania metod interfejsu.

Poniższy przykładowy kod wykonuje przyrostową kompilację klasy, która uzyskuje dostęp do domyślnej metody interfejsu:

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