Java final方法使用静态绑定,但JVM使用" invokevirtual"编译时的指令

时间:2017-03-24 04:53:28

标签: java binding static final invokevirtual

很多书都说java最终实例方法(不是私有)使用静态绑定,而其他实例方法(非私有)使用动态绑定。但是在编译时,它们都使用" invokevirtual" JVM指令。当JVM执行" invokevirtual"时,可以区分最终方法和非最终方法。说明?我原本认为最终方法使用" invokespecial"作为私有实例方法,因为它们都使用静态绑定。

2 个答案:

答案 0 :(得分:2)

编译后的表格是JLS §13.4.17在第13章“二进制兼容性”中的直接结果:

  

13.4.17。 final方法

     

将声明为final的方法更改为不再声明为final不会破坏与现有二进制文件的兼容性。

这意味着调用方的形式不应反映目标方法在编译时是否为final(或当存在不同表示形式时,不允许在运行时产生实际差异)

要与其他形式的调用进行比较,无法在不破坏与调用者兼容性的情况下删除static修饰符,因此,使用专用的invokestatic指令对调用形式进行编码是一致的

对于private方法的调用,调用者必须在同一类中,因此,在添加或删除private修饰符时(仅考虑有效的调用者),将对其进行重新编译,因此使用没有问题。在同一类中调用invokespecial方法时的private。从JDK 11开始,private方法可能会被属于同一嵌套组的其他类中的调用者调用;在这种情况下,其他类中的这些调用者将不使用invokespecial

因此final和非final方法之间的区别确实在运行时发生,当JVM知道实际的目标方法 if 时,这种区别就发生了。符合条件的JVM必须拒绝试图覆盖final方法的类,但是它们不需要对调用进行优化。实际上,当今的JVM能够优化所有未被覆盖的方法的调用,而不管此属性是否已由final修饰符强制执行。唯一的不同是,将新类加载到JVM中会覆盖非final方法,这可能会导致调用方的优化。

答案 1 :(得分:0)

没有其他字节码指令可以调用由invokevirtual以外的类声明的实例方法。它的名字令人困惑。它也可以命名为invokeClassMethodinvokeclass。实际上编译器不会特别处理最终方法。 invokespecial用于调用构造函数和静态初始值设定项。