Hoz*_*ard 5 java jvm bytecode invokevirtual
我有以下代码.
public class Parent {
@Override
public int hashCode() {
return 0;
}
}
public class Child extends Parent {
public void test() {
this.toString();
this.hashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
正如您在上面的代码中看到的那样,Child从Object继承toString(),从Parent继承hashCode().Child#test的字节码操作如下.
ALOAD 0: this
INVOKEVIRTUAL Object.toString() : String
ALOAD 0: this
INVOKEVIRTUAL Child.hashCode() : int
RETURN
Run Code Online (Sandbox Code Playgroud)
我认为如果invokevirtual调用Object.toString(),它应该调用Parent.hashCode()以保持一致性.或者,调用Child.hashCode(),然后调用Child.toString().
但是,当且仅当Object继承目标方法时,invokevirtual才会保持其一致性.
只有这种情况,在Object中调用虚拟调用方法.对于其他情况,请在当前类中调用虚拟调用方法.
我想知道为什么会这样.
根据JVM规范p.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;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
604 次 |
| 最近记录: |