我遇到了 dalvik dex 转换器及其用于调用方法的操作码的问题。基本上我private final
在我的类中定义了一个方法,当调用它时invoke-direct
,dx 不是生成操作码,而是生成invoke-super
. 因为它是一个私有方法,该方法在超类上不存在,所以我在设备上得到了 VFY 违规。我能够找到触发这种情况的确切场景,它似乎在以下情况下发生:
- 使用 JaCoCo 检测类,以及
- 用编译的类
--target 1.6
如果满足这两个条件,则生成的 dex 类具有invoke-super
而不是invoke-direct
. 如果我禁用 JaCoCo 或者如果我使用 编译--target 1.5
,它使用正确的invoke-direct
操作码。
在查看javap
反汇编的类代码时,我可以看到dx
假设 super 而不是直接的原因:
未检测,为 1.6 编译:
$ javap -d com.example.ClassName | grep waitForConnectivity
159: invokespecial #115; //Method waitForConnectivity:()V
$ dexdump -d classes.dex | grep waitForConnectivity
147ad8: 7010 6042 0200 |001e: invoke-direct {v2}, Lcom/example/ClassName;.waitForConnectivity:()V // method@4260
检测,编译为 1.5 ( --target 1.5
):
$ javap -d com.example.ClassName | grep waitForConnectivity
235: invokespecial #115; //Method waitForConnectivity:()V
$ dexdump -d classes.dex | grep waitForConnectivity
149d4c: 7010 9242 0400 |0018: invoke-direct {v4}, Lcom/example/ClassName;.waitForConnectivity:()V // method@4292
仪表化,为 1.6 编译:
$ javap -d com.example.ClassName | grep waitForConnectivity
235: invokespecial #115; //Method com/example/ClassName.waitForConnectivity:()V
$ dexdump -d classes.dex | grep waitForConnectivity
149d4c: 6f10 9242 0400 |0018: invoke-super {v4}, Lcom/example/ClassName;.waitForConnectivity:()V // method@4292
所以不同的是编译的.class文件编译了引用类的完全限定类名的java字节码this
(注意“ //Method waitForConnectivity:()V
” vs“ //Method com/example/ClassName.waitForConnectivity:()V
”)。似乎dx
自动假定如果方法名称是完全限定的,它必须使用invoke-super
,但如果它不是限定的,它使用invoke-direct
.
我的问题是:
- 这是 Android 中的
dx
错误,还是 JaCoCo 中的错误? - 我怎样才能避免这种情况,以便 JaCoCo 检测类可以在我的自动化测试构建中正常工作?
我当前的解决方法是拥有一个 Maven“jacoco”配置文件,并在其中覆盖该${java.version}
属性以将其从默认的“1.6”更改为“1.5”。有没有更好的解决方案?