The Java invokevirtual bytecode operation does not support consistency of methods inherited by Object

I have the 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 can see in the above codes, Child inherits toString () from Object and hashCode () from the parent. The byte code of the Child # test is as follows.

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

I think that if invokevirtual calls Object.toString (), it should call Parent.hashCode () for consistency. or, called by Child.hashCode (), then you need to call Child.toString ().

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

Only in this case does the invokevirtual method call on Object. For other cases, the invokevirtual calls method in the current class.

I want to know why this is happening.

+5
3

, . , . , , , , . .

+4

JVM . 3.7:

. . , .

, Child.hashCode() - , , JVM . , toString() , Object, Object - - , JVM:

  Constant pool:
const #2 = Method   #24.#25;    //  java/lang/Object.toString:()Ljava/lang/String;
...
const #24 = class   #34;    //  java/lang/Object
const #25 = NameAndType #35:#36;//  toString:()Ljava/lang/String;
+5

My theory: it is toString()used very often, so javac uses a common one Object.toString()to keep persistent pool entries.

For example, if the code contains foo.toString() and bar.toString(), for a pool of constants only one is required Object.toStringinstead of two entriesFoo.toString and Bar.toString

Javac probably hard-coded this optimization, rather than parsing the code to see if it is really necessary.

+1
source

All Articles