Note that there are some explanatory texts on larger screens.

plurals
  1. PODalvik transformation using wrong invoke- opcode
    primarykey
    data
    text
    <p>I'm running into a problem with the dalvik dex converter and the opcode it is using to invoke methods. Basically I have a <code>private final</code> method defined in my class, and when calling it, instead of generating the <code>invoke-direct</code> opcode, dx is generating <code>invoke-super</code>. Because it's a private method, the method doesn't exist on the super class, so I get a VFY violation on the device. I was able to track down the exact scenario that triggers this, and it appears to happen when:</p> <ol> <li>instrumenting the classes with JaCoCo, and</li> <li>classes compiled with <code>--target 1.6</code></li> </ol> <p>If those two conditions are met, the resulting dex class has <code>invoke-super</code> instead of <code>invoke-direct</code>. If I disable JaCoCo OR if I compile with <code>--target 1.5</code>, it uses the correct <code>invoke-direct</code> opcode.</p> <p>In looking at the <code>javap</code> disassembled class code, I can see what causes <code>dx</code> to assume super instead of direct:</p> <p><strong>Not instrumented, compiled for 1.6:</strong></p> <pre><code>$ 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 </code></pre> <p><strong>Instrumented, compiled for 1.5 (<code>--target 1.5</code>):</strong></p> <pre><code>$ 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 </code></pre> <p><strong>Instrumented, compiled for 1.6:</strong></p> <pre><code>$ 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 </code></pre> <p>So the difference is that the compiled .class file has compiled java bytecode that references the <em>fully qualified class name</em> of the <code>this</code> class (notice "<code>//Method waitForConnectivity:()V</code>" vs "<code>//Method com/example/ClassName.waitForConnectivity:()V</code>"). It appears that <code>dx</code> automatically assumes that if the method name is fully qualified, it must use <code>invoke-super</code>, but if it's not qualified, it uses <code>invoke-direct</code>.</p> <p>My questions are:</p> <ol> <li>Is this a bug in Android's <code>dx</code>, or a bug in JaCoCo? </li> <li>How can I avoid this, so that the JaCoCo-instrumented classes can work properly in my automated test builds?</li> </ol> <p>My current workaround is to have a Maven "jacoco" profile, and in there I override the <code>${java.version}</code> property to change it from the default "1.6" to "1.5". Is there any better solution?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload