为什么递归函数在随机数上停止?

时间:2019-03-11 18:26:19

标签: java recursion

我写了一个下面显示的小程序,该程序计算无限递归循环在导致StackOverflow错误之前将经过多少次。

let objectsToShare = [textToShare, otherObject] as [Any]
            let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)

        //New Excluded Activities Code
        activityVC.excludedActivityTypes = [UIActivityType.addToReadingList]
        //

        activityVC.popoverPresentationController?.sourceView = sender as? UIView
        self.present(activityVC, animated: true, completion: nil)

问题是,它每次都会错误编号,通常在8000到9000之间。有人能解释为什么会这样吗?

编辑:我正在使用Eclipse IDE,尚未与其他IDE或命令行对其进行测试。

5 个答案:

答案 0 :(得分:7)

JVM规范很好地解释了其与堆栈有关的行为;

  

每个Java虚拟机线程都有一个专用的Java虚拟机   堆栈,与线程同时创建。 Java虚拟机   堆栈存储帧(第2.6节)。 Java虚拟机堆栈类似于   到常规语言(例如C)的堆栈:它保存本地   变量和部分结果,并在方法调用中起作用   然后返回。因为Java虚拟机堆栈永远不会   除了推和弹出框架外,直接操纵的框架可能是堆的   已分配。 Java虚拟机堆栈的内存不需要   是连续的。

     

在Java®虚拟机规范的第一版中,   Java虚拟机堆栈被称为Java堆栈。

     

此规范允许Java虚拟机堆栈为   固定大小或根据需要动态扩展和收缩   计算。如果Java虚拟机堆栈的大小固定,   可以选择每个Java虚拟机堆栈的大小   创建该堆栈时独立运行。

     

Java虚拟机实现可以为程序员或   用户控制Java虚拟机堆栈的初始大小,   以及在动态扩展或收缩Java的情况下   虚拟机堆栈,可控制最大和最小大小。

     

以下与Java Virtual相关的特殊条件   机器堆栈:

     

如果线程中的计算需要更大的Java虚拟机   如果堆栈超出了允许的范围,则Java虚拟机将抛出一个   StackOverflowError。

     

如果Java虚拟机堆栈可以动态扩展,并且   尝试扩展,但可用内存不足   进行扩展,或者如果没有足够的内存   可用于为新的Java虚拟机创建初始堆栈   线程,Java虚拟机将引发OutOfMemoryError。

就您的问题而言,摘录中的重要一点:

  • 该规范允许Java虚拟机堆栈具有固定大小,或者根据计算要求动态扩展和收缩。

由于没有提供堆栈大小,因此JVM尝试动态扩展堆栈大小,因为该函数被递归调用,需要更多的堆栈内存。在每次运行中,它可能会为其堆栈找到不同数量的动态内存,具体取决于运行时计算机上内存的可用性。这就是为什么您在抛出SO错误之前看到的迭代次数值会有所不同的原因。如果(使用Xss<size> JVM参数)为程序配置较小的堆栈大小,则应该在SO错误之前看到几乎相同数量的递归。

答案 1 :(得分:1)

可能与计算机可以为程序分配多少实际内存有关,而计算机中正在运行其他程序和进程

答案 2 :(得分:1)

StackOverflowError是一个错误。作为错误,与JVM有关(错误不是Exception!)。

当您的堆栈(或方法执行堆栈)与您的堆大小(JVM的内存)冲突时,会发生此错误。

可以定义JVM堆的大小,但是可以从堆栈中定义。

答案 3 :(得分:1)

因此,正如其他人指出的那样,您可能必须查看正在使用的jvm,并从那里了解使用了什么垃圾收集器(多久调用一次gc)也是一个不错的练习,因为这可能会给您不仅对堆栈溢出错误有更深入的了解,而且对Java的工作原理有更深入的了解。如果真的很热衷,您可以实现自己的小型JVM,并且可能会有更好的方案。

答案 4 :(得分:0)

当堆栈(内存的一部分,存储了方法执行堆栈的地方)与堆(分配对象,基元等的内存)碰撞时,抛出

StackOverflowError。您无法预测何时引发错误,因为除非由-Xss标志指定,否则堆栈的大小可以是动态的。这就是为什么没有固定的方法执行深度会导致StackOverflowError的原因。