Search code examples
javajvmbytecodeinvokevirtual

Java bytecode operation 'invokevirtual' does not keep consistency for the methods inherited by Object


I have following codes.

public class Parent {

    @Override
    public int hashCode() {
         return 0;
    }

}

public class Child extends Parent {

    public void test() {
        this.toString();
        this.hashCode();
    }

}

As you see in the above codes, Child inherits toString() from Object and hashCode() from Parent. Bytecode operation of Child#test is as following.

ALOAD 0: this
INVOKEVIRTUAL Object.toString() : String
ALOAD 0: this
INVOKEVIRTUAL Child.hashCode() : int
RETURN

I think if invokevirtual calls Object.toString(), it should call Parent.hashCode() for consistency. or, Child.hashCode() called, then Child.toString() should be called.

However, invokevirtual does not keep its consistency if and only if target method is inherited by Object.

Only that case, invokevirtual calls method in the Object. For other cases, invokevirtual calls method in current class.

I want to know why this happens.


Solution

  • You are correct that the compiler behaves unlogical. But the effect of this code is identical to the effect of both variants that you suggested. So this is likely not an intentional behaviour, but result of long evolution of the code of the compiler. Other compilers may produce different code.