任何能够回答这个问题的人都会知道,JVM支持几个用于调用方法的字节码指令(invokevirtual、invokespecial、invokestatic、.)
对实例方法的大多数方法调用都是由invokevirtual进行的,但是私有方法和初始化器方法是通过invokespecial调用的,如JVM规范所述:
invokespecial和invokevirtual指令的不同之处在于,invokevirtual基于对象的类调用方法。invokespecial指令用于调用实例初始化方法以及当前类的超类的私有方法和方法。
据我所知,invokevirtual执行vtable查找来解析方法,而invokespecial则是静态解析的,因为正确的方法实现是在链接时已知的。
我的问题是,在方法所有者的具体类在编译时已知的情况下,为什么不使用invokespecial调用public方法?在我看来,出于效率的原因,避免查找是可取的。但是很明显,我对JVM有一些不理解的地方。
发布于 2019-10-04 18:03:56
首先,在编译时很难知道特定的调用目标。JVM可以动态加载新类,甚至可以在运行时重新定义现有类。在编译时出现非虚拟的公共方法可能会在运行时变成虚拟的。
您是对的,vtable查找可能会对性能产生影响。但是,invokevirtual字节码根本不意味着vtable查找。
例如,HotSpot JVM尽力去虚拟化方法调用。它依赖于类层次分析和运行时类型概要文件将invokevirtual转换为直接调用,甚至更好的是,将“虚拟”方法内联到调用站点。只有真正的大型调用站点(在运行时有3个或更多个目标)才能进行可验证的查找。
也就是说,在现代JVM中,当目标方法实际上是非虚拟的时候,invokespecial和invokevirtual之间没有性能差异。
https://stackoverflow.com/questions/58237483
复制相似问题