我在the Javagony article on esolangs.org中发现了这个代码块:

...在Javagony中,复制循环的最常见方式是通过递归.如果你的循环有太多的步骤,你会得到一个堆栈溢出错误,然而,这是可以捕获的.因此,要创建循环,我们可以从调用自身的函数开始,并try 捕获.

public void loop() {
   try {
       loop();
   catch (StackOverflowException /* sic */ e) {
       loop();
   }
}

好的,我知道你should not"抓住"了StackOverflowError,因为我面前的许多问题已经结束了;但我不禁好奇,如果你只是试图抓住它,could会发生什么?它会给你无限的递归,还是JVM会崩溃和爆炸?

不管怎么说,我是这样写的:

public class Javagony
{
    public static void main(String[] args)
    {
        loop();
    }

    static int n = 1;

    public static void loop()
    {
        System.out.println(n);
        n++;
        try
        {
            loop();
        }
        catch (StackOverflowError _e)
        {
            loop();
        }
    }
}

然后我用java Javagony.java来计算它.从那时起已经有一段时间了,数字一直在滚动.它现在已经达到4072342(相比之下,没有Try Catch块的同一个程序在~40000年年死亡),并且仍在继续.但这怎么可能发生呢?StackOverflowError不是表示资源已经耗尽,函数调用的最大容量已经达到了吗?为什么简单地捕捉和忽略它会使递归继续进行?

PS.进程已中断,请不要担心

推荐答案

好了,我知道你们should not"抓住"了StackOverflowError,因为在我面前提出的许多问题已经结束了;

一般来说,你不应该染上它,因为它通常不是你可以恢复的东西.一般来说,你甚至不能依赖于包装和再扔它.

但我就是忍不住好奇,如果你试着抓住它,会发生什么?它会给你无限的递归吗

不是的.

或者JVM只会崩溃和爆炸?

不是的.

当堆栈上没有空间时,您无法成功调用任何方法或构造函数.这是相当严重的,一般来说,如果你试图从它恢复,那么你很可能只会得到另一个StackOverflowException.但是,当方法终止时,包括抛出StackOverflowException,就会释放一些堆栈空间,这样您就可以做一些事情了.

现在考虑一下您的特定示例.在递归的底部,一些对loop()的调用抛出一个SOE.父调用捕获它,并在处理程序中再次try 递归.有充分的理由预计,这也将抛弃国企,国企将逃脱到更高的水平.但现在that递归调用处理该异常,并且它有足够的堆栈空间再进行一次迭代.当它抛出时,它被再上一级处理,现在有空间再进行two次迭代(每次迭代都是从异常处理的Angular 重新开始的).以此类推.

这不会给您提供无限递归,但它确实极大地放大了在SOE最终从顶层调用冒泡出来之前成功执行有效负载的总次数.

事实上,您可以预期执行有效负载的总次数随可用堆栈空间量呈指数级增长.您不需要有那么大的堆栈空间,就可以提供比您所能使用的更多的总执行.

Java相关问答推荐

Java应用程序崩溃时试图读取联系人从电话

H2弹簧靴试验跌落台

Select 按位运算序列

Spring Batch 5-不要让它在数据库中自动创建表

Java模式匹配记录

连接Quarkus中的两个异步操作

呈现文本和四舍五入矩形时出现的JavaFX窗格白色瑕疵

如何在Spring Java中从数据库列中获取JSON中的具体数据

通过Spring Security公开Spring Boot执行器端点

Java构造函数分支

如何在Cosmos DB(Java SDK)中增加默认响应大小

无法播放音频:从资源加载库GStreamer-Lite失败

根据应用程序 Select 的语言检索数据

如何通过用户ID向用户发送私信

如何使JOOQ渐变脚本不重新创建表未更改的类?

获取401未经授权,即使在标头中设置了浏览器名称和cookie

简化每个元素本身都是 map 列表的列表

如何在更改分辨率时将鼠标坐标计算为世界坐标

using case default on switch语句返回;预览特征切换中的模式匹配仅在源级别20及以上的情况下可用;

在JPanel上使用GridBagLayout并将JButton放在里面时出现问题