当前位置: 首页 > 面试题库 >

Java中的尾调用优化

花欣然
2023-03-14
问题内容

从Java
8开始,Java不提供尾叫优化(TCO)。经过研究,我知道原因是:

在JDK类中,有许多对安全性敏感的方法,它们依赖于对JDK库代码和调用代码之间的堆栈帧进行计数,以确定谁在调用它们。

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

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

笔记:

  1. 我知道TCO处于积压状态,并且优先级较低,但是想知道为什么Java无法像Scala那样在编译时进行更改。

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


问题答案:

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

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

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

据我所知,关于尾音的工作尚未开始,因为“光纤和连续性”似乎是当前的重中之重。



 类似资料:
  • 问题内容: 到目前为止,我一直喜欢JavaScript,并决定使用Node.js作为我的引擎,它声称Node.js提供了TCO。但是,当我尝试使用Node.js运行此(显然是尾部调用)代码时,会导致堆栈溢出: 现在,我做了一些挖掘,发现了这一点。在这里,看来我应该这样写: 但是,这给了我语法错误。我试过它的各种排列,但在所有的情况下,Node.js的似乎不满 的东西 。 本质上,我想了解以下内容:

  • 问题内容: 我尝试在网络上进行挖掘以使问题得到解答。我找到了一些与达芬奇计划有关的文件。这被标记为与在JVM中包含闭包有关的JSR 292。这个项目实现了吗,它是Java 8的一部分吗? 问题答案: 据我所知,Java 8没有尾调用优化。Afaik与实际的编译器技巧无关,因为它很简单,但是为了安全起见保留了一个调用栈。但是我想使用字节码重写器是可能的。

  • 尾部调用优化 (TCO) 正如我们早前简单提到的,ES6包含了一个冒险进入性能世界的具体需求。它是关于在函数调用时可能会发生的一种具体的优化形式:尾部调用优化(TCO)。 简单地说,一个“尾部调用”是一个出现在另一个函数“尾部”的函数调用,于是在这个调用完成后,就没有其他的事情要做了(除了也许要返回结果值)。 例如,这是一个带有尾部调用的非递归形式: function foo(x) { r

  • 问题内容: 在进行了-jvm-prevent-tail-call-optimizations之后的两年,似乎有一个原型 实现,并且MLVM一段时间以来将该功能列为“ proto 80%”。 Sun / Oracle方面对支持尾部调用是否没有积极的兴趣,还是就像JVM所提到的那样,尾部调用“ 注定要在每个功能优先级列表上排在第二位 ”?语言峰会? 如果有人测试了MLVM构建并可以分享一些关于其运行状

  • 尾部调用优化对返回void的函数的递归调用有效吗?例如,我有一个函数,void fun() 在这里,编译器不会知道,调用fun()是最后一条语句。那么尾部调用优化是否只针对返回某些值的函数?

  • 本文向大家介绍C#中尾递归的使用、优化及编译器优化,包括了C#中尾递归的使用、优化及编译器优化的使用技巧和注意事项,需要的朋友参考一下 递归运用 一个函数直接或间接的调用自身,这个函数即可叫做递归函数。 递归主要功能是把问题转换成较小规模的子问题,以子问题的解去逐渐逼近最终结果。 递归最重要的是边界条件,这个边界是整个递归的终止条件。 上面是个经典阶乘函数的实现。这里分2步: 1.转换,把10的阶