Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

d8

d8 は、プロジェクトの Java バイトコードを Android デバイス上で実行可能な DEX バイトコードにコンパイルするために、Android Studio および Android Gradle プラグインで使用されるコマンドライン ツールです。これにより、アプリのコード内で Java 8 言語機能を使用できるようになります。

また、d8 は、Android Build Tools 28.0.1 以降にスタンドアロン ツールとして組み込まれています(android_sdk/build-tools/version/)。

一般的な使用方法

d8 は簡単に使用できます。下記に示すように、必要なのは、DEX バイトコードに変換するコンパイル済み Java バイトコードのパスだけです。

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 SDK の android.jar のパスを指定します。このフラグは、Java 8 言語機能を使用するバイトコードをコンパイルする際に必要になります。
--classpath path プロジェクトの DEX ファイルをコンパイルするうえで d8 が必要とする可能性のあるクラスパス リソースを指定します。特に、d8 を使用して Java 8 言語機能を使用するバイトコードをコンパイルする際には、特定のリソースを指定する必要があります。
--min-api number 出力 DEX ファイルがサポートする最小 API レベルを指定します。
--intermediate このフラグを渡すと、コンパイル対象がプロジェクトの Java バイトコードの完全なセットではないことを d8 に通知できます。このフラグは、デバイス上で実行するための最適化済み DEX ファイルをコンパイルする場合ではなく、増分ビルドを実行する場合に有用です。このフラグを渡すと、d8 により、中間 DEX ファイルが作成され、指定した出力パスまたはデフォルトパスに保存されます。

デバイス上で実行するための DEX ファイルをコンパイルする場合は、このフラグを外して、中間 DEX クラスのパスを入力として指定します。

--file-per-class 各クラスを個別の DEX ファイルにコンパイルします。

このフラグを有効にすると、変更したクラスだけを再コンパイルすることで、より多くの増分ビルドを実施できるようになります。Android Gradle プラグインを使用して増分ビルドを実行する場合、この最適化はデフォルトで有効になっています。

--main-dex-list を指定している場合、このフラグは使用できません。

--no-desugaring Java 8 言語機能を無効にします。Java 8 言語機能を使用する Java バイトコードをコンパイルする予定がない場合に限り、このフラグを使用するようにしてください。
--main-dex-list path d8 でメイン DEX ファイルに含めるべきクラスをリストしたテキスト ファイルを指定します。このファイルは通常、classes.dex という名前にします。このフラグでクラスのリストを指定しない限り、d8 によりどのクラスがメイン DEX ファイルに含められるかは保証されません。

Android システムはアプリの起動時にメイン DEX ファイルを最初にロードするため、このフラグを使用して、特定のクラスをメイン DEX ファイル内にコンパイルすることで、起動時に優先順位を付けることができます。この機能は特に、旧式の multidex をサポートする場合に便利です。実行時に、旧式 multidex ライブラリがロードされるまで、メイン DEX ファイル内のクラスだけが利用可能になります。

各 DEX ファイルは、64K 参照制限を満たしている必要があります。そのため、メイン DEX ファイルに対して、あまりに多くのクラスを指定しないように注意してください。コンパイル エラーが発生します。デフォルトでは、--main-dex-list を使用してクラスを指定した場合、指定したクラスだけが d8 によりメイン DEX ファイル内に格納されます。これにより、メイン DEX ファイル内にないクラスに関する問題をデバッグしやすくなります。--release モードを指定した場合、d8 では、アプリのリリース バージョン内にパッケージ化される DEX ファイルの数を削減するため、64K 制限の下でできる限り多くのクラスをメイン DEX ファイルに格納するよう試みられます。

--file-per-class を指定している場合、このフラグは使用できません。

--version 現在使用している d8 のバージョンを出力します。
--help d8 を使用するためのヘルプテキストを出力します。

増分ビルドを実行する

継続的インテグレーション ビルドなどの開発におけるビルド速度を向上させるために、d8 に対して、プロジェクトの Java バイトコードのサブセットのみをコンパイルするよう指定できます。たとえば、クラス単位の dex 変換を有効にしている場合、前回のビルド以降に変更したクラスだけを再コンパイルできます。

次のコマンドの場合、いくつかのクラスの増分ビルドを実行し、クラス単位の dex 変換を有効にします。また、このコマンドでは、増分ビルドの出力ディレクトリも指定しています。

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

d8 による増分ビルドの際、DEX 出力内に追加情報が保存されます。この追加情報は、後のアプリのフルビルド中に --main-dex-list オプションを正しく処理し、DEX ファイルをマージするために使用されます。たとえば、Java 8 ラムダクラスを処理する場合、d8 では、各入力クラスに対して作成されるラムダクラスがトラッキングされます。フルビルド中、d8 によりクラスがメイン DEX ファイルに格納される際にはメタデータが参照され、そのクラス用に作成されたラムダクラスもすべてメイン DEX ファイル内に格納されます。

複数回にわたる増分ビルドを通して、すでにプロジェクトのすべてのバイトコードを DEX ファイルにコンパイルしてある場合は、以下に示すように、中間 DEX ファイルのディレクトリを d8 に渡すことでフルビルドを実行できます。また、--main-dex-list を使用すると、d8 でメイン DEX ファイル内にコンパイルするクラスを指定できます。この方式のビルドでは、すでに DEX バイトコードにコンパイル済みのファイルのセットを入力に使用するため、クリーンビルドよりも高速になります。

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

Java 8 言語機能を使用するバイトコードをコンパイルする

d8 では、「desugar」と呼ばれるコンパイル プロセスを使用して、コード内での Java 8 言語機能の使用を可能にしています。desugar により、Java 8 の便利な言語機能が、Android プラットフォーム上で実行可能なバイトコードに変換されます。

Android Studio と Android Gradle プラグインには、desugar を有効にするうえで d8 が必要とするクラスパス リソースが含まれています。ただし、コマンドラインから d8 を使用する場合は、明示的にクラスパス リソースを含める必要があります。

そのようなリソースの例として、ターゲット Android SDK の android.jar があり、これには Android プラットフォーム API のセットが含まれています。そのパスは、--lib フラグを使用して指定します。

もう 1 つのリソースとしては、プロジェクトのコンパイル済み Java バイトコードのうち、現時点では DEX バイトコードにコンパイルしていないが他のクラスを DEX バイトコードにコンパイルするうえで必要となる Java バイトコードのセットがあります。たとえば、Java 8 言語機能であるデフォルトおよび静的インターフェース メソッドを使用するコードの場合、必ずしもプロジェクトのすべての Java バイトコードを DEX バイトコードにコンパイルするつもりがない場合でも、このフラグを使用して、すべての Java バイトコードのパスを指定する必要があります。これは、d8 によるプロジェクトのコードの理解と、インターフェース メソッドの呼び出しの解決に、この情報が必要なためです。

次のサンプルコードの場合、デフォルト インターフェース メソッドにアクセスするクラスの増分ビルドを実行します。

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