`d8` is a command-line tool that Android Studio and the Android Gradle plugin
use to compile your project's Java bytecode into DEX bytecode that runs
on Android devices. `d8` lets you use Java 8 language features in your
app's code.

`d8` is also included as a standalone tool in Android Build
Tools 28.0.1 and higher:
<var translate="no">android_sdk</var>`/build-tools/`<var translate="no">version</var>`/`.

## General usage

`d8` requires only a path to the compiled Java bytecode
that you want to convert into DEX bytecode. For example:  

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

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

By default, `d8` compiles the Java bytecode into optimized DEX files
and includes debug information that you can
use to debug your code during runtime. However, you can include optional
flags to perform an incremental build, specify classes that
should be compiled into the main DEX file, and specify paths to
additional resources required to use Java 8 language features.  

```
d8 path-to-input-files [options]
```

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

| Option | Description |
|---|---|
| `--debug` | Compile 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. |
| `--release` | Compile DEX bytecode without debug information. However, `d8` includes some information that's used when generating stacktraces and logging exceptions. Pass this flag when compiling bytecode for a public release. |
| `--output `<var translate="no">path</var> | Specify 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 `<var translate="no">android_sdk</var>`/platforms/`<var translate="no">api-level</var>`/android.jar` | Specify the path to the `android.jar` of your Android SDK. This flag is required when [compiling bytecode that uses Java 8 language features](https://developer.android.com/tools/d8#j8). |
| `--classpath `<var translate="no">path</var> | Specify classpath resources that `d8` may require to compile your project's DEX files. In particular, `d8` requires that you specify certain resources when [compiling bytecode that uses Java 8 language features](https://developer.android.com/tools/d8#j8). |
| `--min-api `<var translate="no">number</var> | Specify 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` | Compile each class into separate DEX files. Enabling this flag lets you 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't use this flag while also specifying `--main-dex-list`. |
| `--no-desugaring` | Disable 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 `<var translate="no">path</var> | Specify a text file that lists classes `d8` should include in the main DEX file, which is typically named `classes.dex`. When you don't specify a list of classes using this flag, `d8` does not guarantee 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](https://developer.android.com/studio/build/multidex). So, don't 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't use this flag while also specifying `--file-per-class`. |
| `--pg-map `<var translate="no">file</var> | Use <var translate="no">file</var> as a mapping file for distribution. |
| `--file-per-class-file` | Produce a separate DEX file per input .class file. Keep synthetic classes with their originating class. |
| `--desugared-lib `<var translate="no">file</var> | Specify a desugared library configuration. <var translate="no">file</var> is a desugared library configuration file in JSON format. |
| `--main-dex-rules `<var translate="no">file</var> | Proguard keep rules for classes to place in the primary DEX file. |
| `--main-dex-list-output `<var translate="no">file</var> | Output resulting main DEX list in file. |
| `--force-enable-assertions [:`<var translate="no">class_or_package_name</var>`...]` `--force-ea [:`<var translate="no">class_or_package_name</var>`...]` | Forcefully enable `javac`-generated assertion code. |
| `--force-disable-assertions [:`<var translate="no">class_or_package_name</var>`...]` `--force-da [:`<var translate="no">class_or_package_name</var>`...]` | Forcefully disable `javac`-generated assertion code. This is the default handling of `javac` assertion code when generating DEX files. |
| `--force-passthrough-assertions [:`<var translate="no">class_or_package_name</var>`...]` `--force-pa [:`<var translate="no">class_or_package_name</var>`...]` | Don't change the `javac`-generated assertion code. This is the default handling of `javac` assertion code when generating `class` files. |
| `--force-assertions-handler:`<var translate="no">handler method</var>` [:`<var translate="no">class_or_package_name</var>`...]` `--force-ah:`<var translate="no">handler method</var>` [:`<var translate="no">class_or_package_name</var>`...]` | Change `javac`- and `kotlinc`-generated assertion code to invoke the method <var translate="no">handler method</var> with each assertion error instead of throwing it. The <var translate="no">handler method</var> is specified as a class name followed by a dot and the method name. The handler method must take a single argument of type `java.lang.Throwable` and have return type `void`. |
| `--thread-count `<var translate="no">number of threads</var> | Specify the number of threads to use for compilation. If not specified, the number is based on heuristics, taking the number of cores into account. |
| `--map-diagnostics[ :`<var translate="no">type</var>`] `<var translate="no">from-level</var>` `<var translate="no">to-level</var> | Map diagnostics of <var translate="no">type</var> (default any) reported as <var translate="no">from-level</var> to <var translate="no">to-level</var>, where <var translate="no">from-level</var> and <var translate="no">to-level</var> are one of 'info', 'warning', or 'error' and the optional <var translate="no">type</var> is either the simple or fully qualified Java type name of a diagnostic. If <var translate="no">type</var> is unspecified, all diagnostics at <var translate="no">from-level</var> are mapped. Note that fatal compiler errors can't be mapped. |
| `--version` | Print the version of `d8` that you're currently using. |
| `--help` | Print help text for using `d8`. |

## Perform incremental builds

To improve build speeds during development, such as for continuous integration
builds, instruct `d8` to compile only a subset of your project's Java
bytecode. For example, if you enable per-class dexing, you can re-compile only
the classes that you have modified since the previous build.
| **Note:** `d8` is unable to detect which bytecode files have been modified automatically. You need to specify the list of classes yourself.

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

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

When `d8` performs an incremental build, it stores additional information in the
DEX output. `d8` later uses that information to correctly process the
`--main-dex-list` option and merge DEX files during a full build of your app.

For example, when processing Java 8 lambda classes, `d8` keeps track of which
lambda classes are created for each input class. During a full build, when `d8`
includes a class in the main DEX file, it consults the metadata to ensure all
of the lambda classes 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 files
across multiple incremental builds, perform a full build by passing the
directory of intermediate DEX files to `d8`, as shown in the following command.
Additionally, you can 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 are
already compiled into DEX bytecode, this build should complete faster
than a clean build.  

```
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 features](https://developer.android.com/studio/write/java8-support)
in your code through a compile process called *desugaring*. Desugaring converts
these useful language features into bytecode that can run on the Android
platform.

Android Studio and the Android Gradle plugin include classpath
resources that `d8` requires to enable desugaring for you. However, when using
`d8` from the command line, you need to include them yourself.

One such resource is the `android.jar` from your target Android SDK. This
resource includes a set of Android platform APIs. Specify its path using
the `--lib` flag.

Another resource is the set of Java bytecode compiled into your project that you
are currently not compiling into DEX bytecode but require to compile other
classes into DEX bytecode.

For example, if your code uses
[default and static interface methods](https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html), which are a Java
8 language feature, you need to use this flag to specify the path to all of your
project's Java bytecode, even if you don't intend to compile all of the bytecode
into DEX bytecode. That's because `d8` requires this information to understand
your project's code and resolve calls to the interface methods.

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

```
d8 MainActivity.class --intermediate --file-per-class --output ~/build/intermediate/dex
--lib <var translate="no">android_sdk</var>/platforms/<var translate="no">api-level</var>/android.jar
--classpath ~/build/javac/debug
```