根据我的理解(并根据https://www.javaworld.com/article/2076949/learn-java/how-the-java-virtual-machine-handles-method-invocation-and-return.html?page=2),JVM按如下方式处理方法调用: 为被调用者创建新的堆栈帧 来自调用者的弹出参数,将它们推送到被调用者 执行被叫。
但是为什么我们必须将参数从一个堆栈复制/移动到另一个堆栈?
为被调用者创建一个新的,重叠的堆栈帧会不会更容易,因此调用者的最顶层插槽(包含参数)现在是callees堆栈帧的最底层插槽。只要我们之后清理所有内容(通过弹出)它就不会有所作为,但是通过避免复制来提高方法调用的效率。
那么问题是什么,我们为什么不这样做?
答案 0 :(得分:2)
您引用的部分描述了一个正式的流程。实现必须与该描述兼容,但不一定要像那样。
如果你只读了几句话,你会发现:
JVM规范不要求Java堆栈的特定实现。帧可以从堆中单独分配,也可以从连续的内存中获取,或者两者都可以。
这解释了为什么不是每个实现都可以像你建议的那样优化它,但是
但是,如果两个帧是连续的,则虚拟机可以只重叠它们,使得一个帧的操作数堆栈的顶部形成下一个的局部变量的底部。在该方案中,虚拟机不需要将objectref和args从一帧复制到另一帧,因为两个帧重叠。调用方法帧中包含objectref的操作数堆栈字与新帧的局部变量0的内存位置相同。
所以没有人说,它不会按照你的建议实施,事实上,这个优化机会已被明确提及。但是本文没有讨论哪个具体的JVM以哪种方式实现堆栈。
同样值得注意的是,对于优化的热点,调用协议可能完全不同,如果没有被调用者内联到调用者,这将完全删除所有调用工件。