MethodInsnNode.itf is not always correct
The field MethodInsnNode.itf is declared with the following comment:
public class MethodInsnNode extends AbstractInsnNode {
...
/**
* If the method's owner class if an interface.
*/
public boolean itf;
...
}
But I've discovered a case when it gives a wrong value.
Suppose we have:
public interface InterfaceWithDefault {
default void foo() {
}
}
A class written in Kotlin programming language (https://kotlinlang.org/)
class KotlinSuperInterfaceDefaultCall : InterfaceWithDefault {
fun bar() {
super.foo()
}
}
We have the following bytecode:
public final bar()V
L0
LINENUMBER 12 L0
ALOAD 0
INVOKESPECIAL InterfaceWithDefault.foo ()V
L1
LINENUMBER 13 L1
RETURN
L2
LOCALVARIABLE this LKotlinSuperInterfaceDefaultCall; L0 L2 0
MAXSTACK = 1
MAXLOCALS = 1
So as you see, the bytecode contains invokespecial instruction. JVM doesn't
prohibit it (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-
6.html#jvms-6.5.invokespecial).
But as I see in org.objectweb.asm.tree.MethodNode#check :
if (insn instanceof MethodInsnNode) {
boolean itf = ((MethodInsnNode) insn).itf;
if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) {
throw new RuntimeException();
}
}
The only expected instruction here is 'invokeinterface'.