d8

d8 is a command line tool that Android Studio and the Android Gradle Pluginuse to compile your project's Java bytecode into DEX bytecode that runson Android devices, and it allows you to use Java 8 language features in yourapp's code.

d8 is also included as a standalone tool in Android BuildTools 28.0.1 and higher:android_sdk/build-tools/version/.

General usage

d8 is simple to use and requires only a path to the compiled Java bytecodethat you want to convert into DEX bytecode, as shown below.

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

The input bytecode can be in any combination of *.class files orcontainers, such as JAR, APK, or ZIP files. You can also includeDEX files for d8 to merge them into the DEX output, which is usefulwhen including output from an incremental build.

By default, d8 compiles the Java bytecode into optimized DEX filesand includes debug information that you canuse to debug your code during runtime. However, you can include optionalflags to, for example, perform an incremental build, specify classes thatshould be compiled into the main DEX file, and specify paths toadditional resources required to use Java 8 language features.

  1. d8 path-to-input-files [options]

The following table describes the optional flags you can use with d8.

OptionDescription
—debug Compiles DEX bytecode to include debug information, such as debug symbol tables.
This option is enabled by default. To include debug information in your DEX bytecode, d8 expects that the input Java bytecode includes that information. For example, if you're using javac to compile your code, you need to pass the -g flag to include debug information in the output Java bytecode.



When compiling DEX files for the release version of your app or library, instead use the —release flag described below.
—release Compiles DEX bytecode without debug information. However, d8 includes some information that's used when generating stacktraces and logging exceptions.
You should pass this flag when compiling bytecode for a public release.
—output path Specifies the desired path for the DEX output. By default, d8 outputs the DEX file(s) in the current working directory.
If you specify a path and name of a ZIP or JAR file, d8 creates the specified file and includes the output DEX files. If you specify the path to an existing directory, d8 outputs the DEX files in that directory.
—lib androidsdk/platforms/api-level/android.jar Specifies the path to the android.jar of your Android SDK. This flag is required when compiling bytecode that uses Java 8 language features.
—classpath path Specifies classpath resources that d8 may require to compile your project's DEX files. In particular, d8 requires you to specify certain resources when compiling bytecode that uses Java 8 language features.
—min-api number Specifies the minimum API level you want the output DEX files to support.
—intermediate Pass this flag to let d8 know that you are not compiling the complete set of your project's Java bytecode. This flag is useful when performing incremental builds—rather than compiling optimized DEX files that you expect to run on a device, d8 creates intermediate DEX files and stores them in the specified output or default path.
When you want to compile DEX files that you intend to run on a device, exclude this flag and specify the path to the intermediate DEX classes as an input.
—file-per-class Compiles each class into separate DEX files.
Enabling this flag allows you to perform more incremental builds by re-compiling only the classes that have changed. When performing incremental builds using the Android Gradle Plugin, this optimization is enabled by default.

You can not use this flag while also specifying —main-dex-list.
—no-desugaring Disables Java 8 language features. Use this flag only if you don't intend to compile Java bytecode that uses Java 8 language features.
—main-dex-list path Specifies a text file that lists classes d8 should include in the main DEX file, which is typically named classes.dex. That is, when you don't specify a list of classes using this flag, d8 does not guarentee which classes are included in the main DEX file.
Because the Android system loads the main DEX file first when starting your app, you can use this flag to prioritize certain classes at startup by compiling them into the main DEX file. This is particularly useful when supporting legacy multidex because only classes in the main DEX file are available at runtime until the legacy multidex library is loaded.

Keep in mind, the each DEX file must still satisfy the the 64K reference limit. So, be sure not to specify too many classes for the main DEX file or you get a compile error. By default, when specifying classes using —main-dex-list, d8 includes _only those classes in the main DEX file—this is to make issues related to classes missing from main DEX file easier to debug. If you specify —release mode, d8 tries to reduce the number of DEX files that are packaged into the release version of your app by including as many other classes in the main DEX file as possible—until the 64K limit is met.

You can not use this flag while also specifying —file-per-class.
—version Prints the version of d8 that you're currently using.
—help Prints help text for using d8

Perform incremental builds

To improve build speeds during development, such as for continuous integrationbuilds, you can instruct d8 to compile only a subset of your project's Javabytecode. For example, if you enable per-class dexing, you can re-compile onlythe classes that you have modified since the previous build.

Note: d8 is unable to detect which bytecode files have beenmodified automatically—you need to specify the list of classes yourself.

The following command performs an incremental build of a few classes and enablesper-class dexing. The command also specifies an output directory for theincremental build.

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

When d8 performs an incremental build, it stores additional information in theDEX output that it later uses to correctly process the —main-dex-listoption and merge DEX files during a full build of your app. For example, whenprocessing Java 8 lambda classes, d8 keeps track of which lamdba classes arecreated for each input class. During a full build, when d8 includes a class inthe main DEX file, it consults the metadata to ensure all of the lambdaclasses created for that class are also included in the main DEX file.

If you have already compiled all of your project's bytecode into DEX filesacross multiple incremental builds, you can perform a full build by passing thedirectory of intermediate DEX files to d8, as shown below. Additionally, youcan specify the classes you want d8 to compile into the main DEX file using—main-dex-list. Because the input is a set of files that is already compiledinto DEX bytecode, this build should complete faster than a clean build.

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

Compile bytecode that uses Java 8 language features

d8 enables you to use Java 8 language featuresin your code through a compile process called desugaring, which converts theseuseful language features into bytecode that can run on the Android platform.

Android Studio and the Android Gradle Plugin include classpathresources that d8 requires to enable desugaring for you. However, when usingd8 from the command line, you need to include them yourself.

One such resource is the android.jar from your target Android SDK. Thisresource includes a set of Android platform APIs, and you specify its path usingthe —lib flag.

Another resource is the set of your project's compiled Java bytecode that youare currently not compiling into DEX bytecode but require to compileother classes into DEX bytecode. For example, if your code usesdefault and static interface methods, which is a Java8 language feature, you need to use this flag to specify the path to all of yourproject's Java bytecode, even if you don't intend to compile all of it into DEXbytecode. That's because d8 requires this information to understandyour project's code and resolve calls to the interface methods.

The following code sample performs an incremental build of a class that accessesa default interface method:

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