d8

d8은 Android 스튜디오 및 Android Gradle 플러그인에서 프로젝트의 자바 바이트코드를 Android 기기에서 실행되는 DEX 바이트코드로 컴파일하는 명령줄 도구로, 이 도구를 사용하면 앱의 코드에 자바 8 언어 기능을 사용할 수 있습니다.

d8은 Android 빌드 도구 28.0.1 이상에 독립 실행형 도구로도 포함됩니다. android_sdk/build-tools/version/.

일반 사용법

d8은 간단하게 사용할 수 있으며, 아래와 같이 DEX 바이트코드로 전환하려는 컴파일된 자바 바이트코드의 경로만 필요합니다.

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

입력 바이트코드는 *.class 파일 또는 JAR, APK, ZIP 파일과 같은 컨테이너의 조합입니다. d8에서 DEX 출력에 병합하도록 DEX 파일을 포함할 수 있으며, 이 기능은 단계식 빌드의 출력을 포함하는 경우에 유용합니다.

기본적으로, d8은 자바 바이트코드를 최적화된 DEX 파일로 컴파일하며 런타임에 코드를 디버깅하는 데 사용할 수 있는 디버그 정보를 포함합니다. 하지만, 예를 들어 단계식 빌드를 실행하고, 기본 DEX 파일로 컴파일해야 하는 클래스를 지정하고, 자바 8 언어 기능을 사용하는 데 필요한 추가 리소스의 경로를 지정하기 위해 선택적 플래그를 포함할 수 있습니다.

    d8 path-to-input-files [options]
    

다음 표에서는 d8과 함께 사용하는 선택적 플래그를 설명합니다.

옵션 설명
--debug 디버그 기호 표 등 디버그 정보를 포함하도록 DEX 바이트코드를 컴파일합니다.

이 옵션은 기본적으로 사용 설정됩니다. DEX 바이트코드에 디버그 정보를 포함하기 위해 d8은 입력 자바 바이트코드에 해당 정보가 포함되어 있을 것으로 예상합니다. 예를 들어, javac를 사용하여 코드를 컴파일하는 경우 -g 플래그를 전달하여 출력 자바 바이트코드에 디버그 정보를 포함해야 합니다.

앱의 출시 버전 또는 라이브러리용 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의 경로를 지정합니다. 이 플래그는 자바 8 언어 기능을 사용하는 바이트코드를 컴파일하는 경우에 필요합니다.
--classpath path d8에서 프로젝트의 DEX 파일을 컴파일할 때 필요할 수도 있는 클래스 경로 리소스를 지정합니다. 특히 d8에서 자바 8 언어 기능을 사용하는 바이트코드를 컴파일하는 경우 특정 리소스를 지정해야 합니다.
--min-api number 출력 DEX 파일이 지원할 최소 API 레벨을 지정합니다.
--intermediate 프로젝트의 자바 바이트코드 전체를 컴파일하지 않는다는 것을 d8에 알리려면 이 플래그를 전달하세요. 이 플래그는 기기에서 실행될 것으로 예상되는 최적화된 DEX 파일을 컴파일하는 대신 단계식 빌드를 실행할 때 유용합니다. d8은 중간 DEX 파일을 만들어 지정된 출력 또는 기본 경로에 저장합니다.

기기에서 실행하려는 DEX 파일을 컴파일하려면 이 플래그를 제외하고 중간 DEX 클래스의 경로를 입력으로 지정하세요.

--file-per-class 각 클래스를 별도의 DEX 파일로 컴파일합니다.

이 플래그를 사용 설정하면 변경된 클래스만 다시 컴파일하여 증분 빌드를 더 실행할 수 있습니다. Android Gradle 플러그인을 사용하여 증분 빌드를 실행하는 경우 이 최적화가 기본적으로 사용 설정됩니다.

--main-dex-list도 지정하는 경우 이 플래그를 사용할 수 없습니다.

--no-desugaring 자바 8 언어 기능을 사용 중지합니다. 자바 8 언어 기능을 사용하는 바이트코드를 컴파일하지 않을 경우에만 이 플래그를 사용하세요.
--main-dex-list path d8에서 기본 DEX 파일에 포함해야 하는 클래스가 나열된 텍스트 파일을 지정합니다. 보통 이 파일의 이름은 classes.dex입니다. 즉, 이 플래그를 사용하여 클래스 목록을 지정하지 않으면 d8에서 어느 클래스가 기본 DEX 파일에 포함되는지 보장하지 않습니다.

앱을 시작할 때 Android 시스템이 기본 DEX 파일을 먼저 로드하기 때문에 이 플래그를 사용하여 시작 시 특정 클래스를 기본 DEX 파일로 컴파일하여 우선순위를 정할 수 있습니다. 이 옵션은 기존 multidex 라이브러리가 로드될 때까지 런타임에 기본 DEX 파일의 클래스만 사용할 수 있기 때문에 기존 multidex를 지원하는 경우 특히 유용합니다.

각 DEX 파일은 여전히 64K 참조 한도를 충족해야 합니다. 따라서 기본 DEX 파일에 너무 많은 클래스를 지정하지 마세요. 너무 많은 클래스를 지정하면 컴파일 오류기가 발생합니다. 기본적으로, --main-dex-list를 사용하여 클래스를 지정하면 d8에서 해당 클래스_만_ 기본 DEX 파일에 포함합니다. 이에 따라 기본 DEX 파일에서 누락된 클래스와 관련된 문제를 더 쉽게 디버깅할 수 있습니다. --release 모드를 지정하면 d8에서 64K 한도에 도달할 때까지 기본 DEX 파일에 다른 클래스를 가능한 한 많이 포함하여 앱의 출시 버전으로 패키징되는 DEX 파일의 수를 줄이려고 시도합니다.

--file-per-class도 지정하는 경우 이 플래그를 사용할 수 없습니다.

--version 현재 사용 중인 d8의 버전을 표시합니다.
--help d8 사용에 관한 도움말 텍스트를 표시합니다.

증분 빌드 실행

지속적 통합 빌드의 경우와 같이 개발하는 동안 빌드 속도를 향상하기 위해 d8에 프로젝트의 자바 바이트코드의 하위 집합만 컴파일하도록 할 수 있습니다. 예를 들어 클래스당 덱싱을 사용 설정하면 이전 빌드 이후에 수정한 클래스만 다시 컴파일할 수 있습니다.

다음 명령어는 증분 빌드를 실행하고 클래스당 덱싱을 사용 설정합니다. 또한 증분 빌드를 위한 출력 디렉터리도 지정합니다.

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

d8은 증분 빌드를 실행할 때 --main-dex-list 옵션을 올바로 처리하고 앱을 전체 빌드하는 동안 DEX 파일을 병합하기 위해 나중에 사용할 DEX 출력에 추가 정보를 저장합니다. 예를 들어 d8은 자바 8 람다 클래스를 처리할 때 각 입력 클래스에 어떤 람다 클래스가 생성되는지 추적합니다. 전체 빌드하는 동안 기본 DEX 파일에 클래스를 포함하는 경우 d8은 메타데이터를 참조하여 해당 클래스에 생성된 람다 클래스가 기본 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
    

자바 8 언어 기능을 사용하는 바이트코드 컴파일

d8를 사용하면 디슈가링이라고 하는 컴파일 프로세스를 통해 코드에서 자바 8 언어 기능을 사용할 수 있습니다. 이 프로세스에서는 이 유용한 언어 기능을 Android 플랫폼에서 실행할 수 있는 바이트코드로 변환합니다.

Android 스튜디오와 Android Gradle 플러그인에는 d8에서 디슈가링을 사용 설정하는 데 필요한 클래스 경로 리소스가 포함되어 있습니다. 하지만 명령줄에서 d8을 사용하는 경우 이 리소스를 직접 포함해야 합니다.

이러한 리소스 중 하나는 대상 Android SDK의 android.jar입니다. 이 리소스에는 Android 플랫폼 API의 집합이 포함되며 --lib 플래그를 사용하여 경로를 지정합니다.

또 하나의 리소스는 현재 DEX 바이트코드로 컴파일하지 않지만 다른 클래스로 DEX 바이트코드로 컴파일하는 데 필요한 프로젝트의 컴파일된 자바 바이트코드의 집합입니다. 예를 들어, 코드에서 자바 8 언어 기능인 기본 및 정적 인터페이스 메서드를 사용하는 경우 프로젝트의 모든 자바 바이트코드를 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