前言
在 JDK1.8 之前我们可以通过 dx 工具将 jar 转为 dex。
为了能够支持 JDK1.8,目前 AGP 是通过在 D8/R8 将 class 文件编译成 dex 文件的过程中,对字节码进行转换来实现的,这个转换过程称为脱糖。
因此 JDK1.8 及以后我们需要使用 d8 工具将 jar 转为 dex。
dx
dx 位于AndroidSDK/build-tools/<33.0.0的版本号
中。
- windows 电脑可以直接在目录下执行 dx,mac 需要
./dx
来执行。 - 建议将
AndroidSDK/build-tools/<33.0.0的版本号
配置到环境变量中。
如果你的项目使用的 JDK 版本<1.8,你完全可以使用 dx。
如果你的项目使用的 JDK 版本>=1.8,但是不包含 Lambda 等需要脱糖的代码,经实验也可使用 dx。
dx 命令行使用如下:
dx --dex --output=输出 目标.jar
Output name must end with one of: .dex .jar .zip .apk or be a directory.
如:
dx --dex --output=dexlib_dex.jar dexlib.jar
如果报错提示:
Uncaught translation error: com.android.dx.cf.code.SimException: ERROR in com.demon.dexlib.TestActivity.onCreate:(Landroid/os/Bundle;)V: invalid opcode ba - invokedynamic requires --min-sdk-version >= 26 (currently 13)
1 error; aborting
说明你的项目中有需要脱糖的代码。
虽然可以加上–min-sdk-version=26 去解决报错,继续生成 dex。
dx --dex --min-sdk-version=26 --output=dexlib_dex.jar dexlib.jar
但是运行使用会崩溃,因此慎用!!!
java.lang.NoSuchMethodError: No static method metafactory(Ljava/lang/invoke/MethodHandles$Lookup
d8
现在的 Android 项目普遍都是>=JDK1.8,会在 build.gradle 中配置:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
d8 位于AndroidSDK/build-tools/>=28.0.1的版本号
中。
- windows 电脑可以直接在目录下执行 d8,mac 需要
./d8
来执行。 - 建议将
AndroidSDK/build-tools/>=28.0.1的版本号
配置到环境变量中。
d8 命令行使用如下:
d8 --output 输出 目标.jar
Output must be a .zip or .jar archive or an existing directory
如:
d8 --output dexlib_dex.jar dexlib.jar
参考
U8 打包把 dx 替换为 d8
逆向开发使用 dx.jar、d8.jar、baksmali.jar 将 jar 转 dex 文件,解决 requires --min-sdk-version >= 26 (currently 13)问题
ASM 字节码插桩:从 Lambda 表达式讲起