Java中的尾调用优化

45
截至Java 8,Java不提供尾调用优化(TCO)。在研究它时,我了解到原因
在JDK类中[...]有许多安全敏感的方法,这些方法依靠计算JDK库代码和调用代码之间的堆栈帧数量来确定谁在调用它们。
然而基于JVM的Scala支持尾调用优化。Scala在编译时进行尾递归优化。为什么Java不能采用相同的方法?
PS:不确定最新版本(目前是Java 11)是否具有TCO。如果有人知道,能够分享一下就好了。
注意事项:
1. 我知道TCO处于积压状态,并且优先级较低,但想知道为什么Java不能像Scala那样在编译时进行更改。
2. Java没有尾调用优化的原因与大多数命令式语言没有它的原因相同。命令式循环是该语言的首选风格,程序员可以用命令式循环替换尾递归。(来源

是的,好多了。 - Ousmane D.
这篇关于JVM中“hard tail call”指令的博客文章来自2007年。在评论部分的末尾,Matthias Felleisen说:“虽然有点晚了,但Java中的TCO将是如此伟大,为什么不再次唤起这个话题呢?关于TCO的一个常见误解是由于‘优化’一词。它确实是一种空间优化(不要使用比goto更多的空间,正如Guy在1970年代所说),但语言应该实现TCO以支持适当的设计...” - David Tonhofer
换句话说,阅读面向对象设计模式书籍并检查所有小模式。选择一些模式,比如解释器或组合模式,并相应地设计您的Java程序。然后运行压力测试并哭泣。即使所有方法调用都是尾递归的,Java也会崩溃,因为它不支持TCO。现在在PLT Scheme的类系统中执行相同的操作并微笑。它可以正常工作-对于所有输入。请参阅我的ECOOP主题演讲(2004年)以获取更多详细信息-Matthias。在JVM中实现这似乎有点困难。 - David Tonhofer
问题[JDK-6804517:某些语言需要能够执行尾调用]已于2009年2月12日提交,更新于2018年10月5日。可能不适用于Java 13(更像Java 9.3,对吧?) - David Tonhofer
1
Java编译器几乎没有任何优化。各种JVM,特别是HotSpot,都进行各种优化,但显然不包括这个。请注意,Scala不用于编译底层JDK,这可能可以解释。 - user207421
显示剩余3条评论
2个回答

22
为什么Java不能使用相同的方法?我无法确定会使用哪种方法,但在“Loom项目提案”中已经很好地解释了它:(链接)。由于向JVM添加操作调用栈的能力肯定是必需的,因此该项目的目标还包括添加一种更轻量级的构造,允许将堆栈退回到某个点,然后以给定的参数调用方法(基本上是有效尾调用的泛化)。我们将称之为取消和调用功能,或UAI。该项目的目标不是向JVM添加自动尾调用优化。据我所知,尾调用尚未开始工作,因为Fiber和Continuation似乎目前更受关注。

4
有更新吗?JVM中的TCO一直期待已久。 - J. Mini

16

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

然而,他们博客上的代码无法编译,所以我创建了一个小型仓库,使用他们的代码并修复了语法,使其能够编译。 带有可工作代码的Github仓库

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接