很多书都说java的最终实例方法(不是私有的)使用静态绑定,而其他实例方法(不是私有的)使用动态绑定。但是,在编译时,它们都使用"invokevirtual“JVM指令。当JVM执行"invokevirtual“指令时,最终方法和非最终方法有区别吗?我最初认为final方法使用"invokespecial“作为私有实例方法,因为它们都使用静态绑定。
发布于 2019-03-21 21:08:13
编译后的形式是第13章“二进制兼容性”中JLS §13.4.17的直接结果:
13.4.17。
final方法
将声明为final的方法更改为不再声明为final不会破坏与预先存在的二进制文件的兼容性。
这意味着调用者的形式不应该反映目标方法在编译时是否为final (或者当存在不同的表示时,不允许在运行时产生实际差异)。
与其他形式的调用相比,在不破坏与调用者兼容性的情况下移除static修饰符是不可能的,因此,使用专用invokestatic指令对调用形式进行编码是一致的。
对于private方法的调用,调用者必须在同一个类中,因此在添加或删除private修饰符时会重新编译(仅考虑有效的调用者),因此在同一个类中调用private方法时使用invokespecial是没有问题的。从JDK版本11开始,属于同一嵌套组的其他类中的调用者可能会调用private方法;在这种情况下,其他类中的这些调用者不会使用invokespecial。
因此,final和非final方法之间的区别确实发生在运行时,当JVM知道实际的目标方法时,如果有这种区别的话。符合要求的JVM必须拒绝试图覆盖final方法的类,但它们不需要执行关于调用的优化。在实践中,今天的JVM能够优化所有未被覆盖的方法的调用,而不管此属性是否已由final修饰符强制执行。惟一的区别是,将覆盖非final方法的新类加载到JVM中可能会导致调用方的反优化。
发布于 2017-03-24 13:15:11
除了invokevirtual之外,没有其他字节码指令可以调用由类声明的实例方法。它的名字令人困惑。它也可以命名为invokeClassMethod或invokeclass。实际上,编译器并不特别对待final方法。invokespecial用于调用构造函数和静态初始值设定项。
https://stackoverflow.com/questions/42991664
复制相似问题