.class 到 .dex 的转换

Conversion of .class to .dex

我有 1 个 java 程序正在使用 Android Keystore APIs。 我们需要 运行 这个程序来验证基于 android 的电路板上的一些符号操作。

运行 这个程序通过 android studio 工作正常,即创建一个示例应用程序并安装该 apk。 但是我们需要通过命令行运行这个程序,因为实际的程序不会是apk格式。

尝试将此程序转换为 dex 格式时出现错误。

通过将android.jar作为类路径传递,编译成功

javac -cp /<path>/Android/Sdk/platforms/android-23/android.jar  ApiClientAndroidKeyStore.java

但是 dex 转换失败并出现以下错误:

UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.RuntimeException: Exception parsing classes
    at com.android.dx.command.dexer.Main.processClass(Main.java:752)
    at com.android.dx.command.dexer.Main.processFileBytes(Main.java:718)
    at com.android.dx.command.dexer.Main.access00(Main.java:85)
    at com.android.dx.command.dexer.Main$FileBytesConsumer.processFileBytes(Main.java:1645)
    at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284)
    at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
    at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
    at com.android.dx.command.dexer.Main.processOne(Main.java:672)
    at com.android.dx.command.dexer.Main.processAllFiles(Main.java:574)
    at com.android.dx.command.dexer.Main.runMonoDex(Main.java:311)
    at com.android.dx.command.dexer.Main.run(Main.java:277)
    at com.android.dx.command.dexer.Main.main(Main.java:245)
    at com.android.dx.command.Main.main(Main.java:106)
Caused by: com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000)
    at com.android.dx.cf.direct.DirectClassFile.parse0(DirectClassFile.java:472)
    at com.android.dx.cf.direct.DirectClassFile.parse(DirectClassFile.java:406)
    at com.android.dx.cf.direct.DirectClassFile.parseToInterfacesIfNecessary(DirectClassFile.java:388)
    at com.android.dx.cf.direct.DirectClassFile.getMagic(DirectClassFile.java:251)
    at com.android.dx.command.dexer.Main.parseClass(Main.java:764)
    at com.android.dx.command.dexer.Main.access00(Main.java:85)
    at com.android.dx.command.dexer.Main$ClassParserTask.call(Main.java:1684)
at com.android.dx.command.dexer.Main.processClass(Main.java:749)

进一步调试发现 android.jar 仅包含 API defns,但实际源代码不存在。

1) 是否有包含源代码的 android.jar 可用(大小可能是个问题)

2) 我们能否在 dex 转换步骤传递源代码

3) apk 是否也包含源代码,而构建或引用就足够了

4) 我们可以从命令行使用与 android studio 在构建 apk 时使用的相同命令吗

问题是bad class file magic (cafebabe) or version (0034.0000)。版本 0x34(十进制 52)是一个 java 8 class 文件,旧版本的 dx 无法处理。

有两种方法可以解决这个问题。首先是 运行 android sdk 管理器并获取最新版本的构建工具。这应该包含更新版本的 dx 工具,它可以处理 java 8 class 个文件。

另一个解决方案是告诉 javac 使用 -source 和 -target 标志为 java 的早期版本编译。例如

javac -source 1.7 -target 1.7 -cp /<path>/Android/Sdk/platforms/android-23/android.jar  ApiClientAndroidKeyStore.java

关于 android.jar 文件只包含存根 - 这是正常的,无需担心。 javac 只需要编译存根。这些 classes 由 Android 框架提供,不包含在您的应用程序中。所以 javac 实际上并不需要 class 具有那些 classes 的完整实现的文件——它只需要知道 class/method/field 签名,这样它就可以正确地 link反对他们。