Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么JVM仍然不支持尾部调用优化?_Java_Language Agnostic_Optimization_Jvm_Tail Call Optimization - Fatal编程技术网

Java 为什么JVM仍然不支持尾部调用优化?

Java 为什么JVM仍然不支持尾部调用优化?,java,language-agnostic,optimization,jvm,tail-call-optimization,Java,Language Agnostic,Optimization,Jvm,Tail Call Optimization,两年后,似乎出现了一个新的应用程序,并将该功能列为“proto 80%”已经有一段时间了 Sun/Oracle方面是否对支持尾部调用没有积极的兴趣,或者只是尾部调用“[…]注定会在每个功能优先级列表[…]中排名第二”,正如在会议上提到的那样 如果有人测试过MLVM构建,并能分享一些关于它工作得如何的印象(如果有的话),我会非常感兴趣 更新:请注意,有些VM支持正确的尾部调用,没有任何问题。Java是您可能想象得到的最不实用的语言(好吧,好吧!),但这对于JVM语言来说是一个很大的优势,例如 我的

两年后,似乎出现了一个新的应用程序,并将该功能列为“proto 80%”已经有一段时间了

Sun/Oracle方面是否对支持尾部调用没有积极的兴趣,或者只是尾部调用“[…]注定会在每个功能优先级列表[…]中排名第二”,正如在会议上提到的那样

如果有人测试过MLVM构建,并能分享一些关于它工作得如何的印象(如果有的话),我会非常感兴趣


更新:请注意,有些VM支持正确的尾部调用,没有任何问题。

Java是您可能想象得到的最不实用的语言(好吧,好吧!),但这对于JVM语言来说是一个很大的优势,例如


我的观察结果是,让JVM成为其他语言的平台似乎从来都不是Sun的首要任务,我想现在是Oracle的首要任务。

也许你已经知道这一点,但这个特性并不像听起来那么简单,因为Java语言实际上向程序员公开了堆栈跟踪

考虑以下计划:

public class Test {

    public static String f() {
        String s = Math.random() > .5 ? f() : g();
        return s;
    }

    public static String g() {
        if (Math.random() > .9) {
            StackTraceElement[] ste = new Throwable().getStackTrace();
            return ste[ste.length / 2].getMethodName();
        }
        return f();
    }

    public static void main(String[] args) {
        System.out.println(f());
    }
}
即使这有一个“尾部调用”,它可能不会被优化。(如果对其进行了优化,仍然需要对整个调用堆栈进行簿记,因为程序的语义依赖于它。)

基本上,这意味着在仍然向后兼容的情况下很难支持它。

()解释了JVM不支持尾部调用优化的原因


但是,尽管众所周知如何将尾部递归函数自动转换为简单循环,Java规范并不要求进行这种转换。据推测,它不是需求的一个原因是,一般来说,转换不能在面向对象语言中静态进行。相反,从尾部递归函数到简单循环的转换必须由JIT编译器动态完成

然后给出了一个不会转换的Java代码示例

因此,如清单3中的示例所示,我们不能期望静态编译器在保留语言语义的同时对Java代码执行尾部递归转换。相反,我们必须依靠JIT的动态编译。根据JVM的不同,JIT可以这样做,也可以不这样做

然后,它提供了一个测试,您可以使用它来确定JIT是否做到了这一点

当然,由于这是一篇IBM论文,它包含一个插件:

我和几个朋友一起运行了这个程序 Java SDK,结果是 令人惊讶的在太阳的热点上运行 1.3版的JVM揭示了 Hotspot不执行以下操作: 转型在默认设置下, 堆栈空间在更少的时间内耗尽 在我的机器上一秒钟都没有。上 另一方面,IBM 1.3版的JVM 咕噜咕噜地说,没有问题, 表示它确实转换了 以这种方式编码


我在过去看到的不在Java中实现TCO(这被认为是困难的)的一个原因是JVM中的权限模型是堆栈敏感的,因此尾部调用必须处理安全方面的问题

我相信Clements和Felleisen[1][2]证明这不是一个障碍,我很确定问题中提到的MLVM补丁也解决了这个问题

我意识到这并不能回答你的问题;只是添加有趣的信息


  • 这不是Java的问题。。。它是JVM中的一个。Java只是JVM语言中最伟大的语言

    创建TCO是在删除当前堆栈帧时跳转到下一个堆栈帧,在正在运行的程序和当前堆栈之间,调用变量应该在其他地方…;)

    最好的方法是为其他帧中的跳转调用创建一个新的特殊调用操作码。他们已经为虚拟通话做了这些。JIT在解释方面并不是一个真正的问题,它可能会引发其他问题,而且JVM已经足够膨胀了

    在Java或其他语言中,由于没有适当的TCO,另一种方法是蹦床,但它添加了大量代码。或者使用特定的异常,但这会带来很多麻烦。它在您的代码中,但不在其他库中

    啊!!如果Rich Hickey添加了一个(重现…)东西(它不是一个函数),那是因为缺乏真正的TCO,他不想让人们认为有一个。他可以很容易地在内部追尾中自动生成TCO。它还有助于检测不在尾部位置的错误尾部调用

    还有一个(蹦床…)的东西用于外部TCO,但它很凌乱(作为蹦床),除了在可怕的堆栈情况下,它很少使用

    但是,是的,很多虚拟机管理TCO。我听说CLR会的。我甚至见过一个付费JVM来管理它(很久以前,不记得了…)

    js中的蹦床示例:


    一篇关于HotSpot VM上的TCO和框架覆盖的老论文:

    据报道,Sun公司的员工大量离开Oracle,除非Oracle明确表示,否则我预计当前的任何项目都不会继续:(请注意,您接受的答案是完全错误的。尾部调用优化和OOP之间没有根本的冲突,当然,像OCaml和F#这样的几种语言都有OOP和TCO。好吧,调用OCaml和F#OOP语言首先是一个糟糕的笑话。但是,是的,OOP和TCO没有太多共同点,除了runt之外ime必须检查正在优化的方法是否在其他地方被覆盖/子类化。+1来自C背景,我一直认为TCO在任何现代JVM中都是给定的。我从未想过要进行实际检查,当我进行检查时,结果令人惊讶…@soc:“除了运行时必须检查正在优化的方法是否在其他地方被重写/子类化这一事实之外”。你的“事实”完全是胡说八道。@Thorbjørn-我写了一个程序来预测任何给定的程序是否会在有限的时间内停止。这花了我很多时间!我使用的第一个基本知识没有函数,而是