私はdalvik dexコンバータとメソッドを呼び出すために使用しているオペコードに問題があります。基本的には私のクラスでprivate final
メソッドが定義されていて、それを呼び出すときにinvoke-direct
オペコードを生成する代わりに、dxはinvoke-super
を生成しています。プライベートメソッドなので、メソッドはスーパークラスには存在しないため、デバイス上でVFY違反が発生します。私はこれをトリガし、正確なシナリオを追跡することができました、そして、場合に発生することが表示されます。間違ったinvoke-opcodeを使用したDalvik変換
- がJaCoCoを持つクラスをインストルメント、および
- クラスは
--target 1.6
でコンパイルしたものを二つの条件の場合結果のdexクラスがinvoke-direct
の代わりにinvoke-super
になっています。 JaCoCoを無効にした場合、または--target 1.5
でコンパイルすると、正しいinvoke-direct
オペコードが使用されます。
、インストルメントされていないが、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 // [email protected]
は、コンパイルされ、インストルメントjavap
解体クラスのコードを見て
、私はスーパーの代わりに、直接の前提とするdx
の原因となるものを見ることができます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 // [email protected]
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 // [email protected]
ので差がコンパイルされた.classファイルがthis
クラスの完全修飾クラス名を参照するJavaバイトコード(通知「//Method waitForConnectivity:()V
」対をコンパイルしたことがあります"//Method com/example/ClassName.waitForConnectivity:()V
")。 dx
は、メソッド名が完全修飾されている場合はinvoke-super
を使用する必要があると自動的に判断しているようですが、修飾されていない場合はinvoke-direct
が使用されます。
私の質問は以下のとおりです。
- が、これはAndroidの
dx
、またはJaCoCoのバグのバグですか? - これを避けると、JaCoCoインストルメントクラスが自動テストビルドで正しく動作するようになりますか?
私の現在の回避策は、Mavenの「jacoco」プロファイルを持っていることであり、そこに私が「1.5」にデフォルトの「1.6」からそれを変更する${java.version}
プロパティをオーバーライドします。もっと良い解決策はありますか?
これは、 'ref.getDefiningClass()!= method.getDefiningClass()'を意味します。私は今日あなたのためにもっと完全なダンプを取ろうとします。しかし、この問題は、JaCoCoのオフライン計測とJava 1.6コンパイラを使って簡単に再現可能であるようです。興味深いことに、それは常にこのように壊れていなかったので、何か他のことも起こっているのは間違いないでしょう。私はそれがいつ始まったのか分かりません。 – Joe
賞金を授与しているのは、あなたが賞金要件の信頼できる部分を満たしているからです。それはまだ解決されていないか、または理由/原因に戻って追跡されていませんが、 'dx'が依然として呼び出されたメソッドの定義クラスを認識できる必要があるとは思いますが、JaCoCo instrumenter invokerの定義クラスと等しく、結果として 'INVOKE_DIRECT'が期待通りに発生します。提案されているようにさらに調査する必要があります。おそらく私はこれに戻る時間があるので、後でチャットでこれを続けることができます。 – Joe
ありがとう!私が言ったように、 'dx --dump'は違いの正確な性質を正確に示すのに役立ちます。私は「dx」が完璧ではないと主張するつもりはないが(誇りは私に欲しいと思うが)、JaCoCoは少なくとも確かに少なくともある程度は疑わしいことをしている。 – danfuzz