Java 中的 Tail Call Optimization

从Java 8开始,Java不提供尾调用优化(TCO)。在研究它时,我开始知道原因是

在JDK类[...]中,有许多安全敏感方法依赖于计算JDK库代码之间的堆栈帧并调用代码来找出谁在调用它们。

然而,基于JVM的Scala支持尾部调用优化。Scala在编译时进行尾部递归优化。为什么Java不能使用相同的方法?

PS:不确定Java的最新版本(截至现在的Java 11)现在是否有TCO。如果一些知道的人也可以分享这一点,那就太好了。

笔记:

  1. 我知道TCO处于积压状态并且优先级较低,但想知道为什么Java不能在编译时进行类似于Scala的更改。

  2. Java没有尾部调用优化,原因与大多数命令式语言没有的原因相同。命令式循环是该语言的首选风格,程序员可以用命令式循环替换尾递归。(来源)


答案 1

为什么Java不能使用相同的方法?

我不能说将使用哪种方法,但是在Project Loom的提案中得到了更好的解释:

由于毫无疑问需要将操作调用堆栈的能力添加到JVM中,因此该项目的目标也是添加一个重量更轻的构造,该构造将允许将堆栈展开到某个点,然后调用具有给定参数的方法(基本上是高效尾部调用的泛化)。我们将该功能称为展开和调用,或UAI。此项目的目标不是向 JVM 添加自动尾部调用优化。

据我所知,尾部调用的工作尚未开始,因为Fibers和Continuouss目前似乎是一个更高的优先级。


答案 2

我在这里读了一篇非常好的博客文章,关于如何在Java中实现尾递归:Knoldus关于Java尾递归的博客文章

但是,他们博客上的代码无法编译,因此我使用他们的代码创建了一个小存储库,但修复了语法以进行编译。包含工作代码的 Github 存储库

希望这对某人有用,我发现Knoldus博客文章中提出的想法非常有趣。

编辑:实际上我后来发现博客文章中提出的想法最初是Venkat Subramaniam的。他在这里的演讲中讨论了这些主题。


推荐