Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.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 为什么递归函数在随机数上停止?_Java_Recursion - Fatal编程技术网

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

Java 为什么递归函数在随机数上停止?,java,recursion,Java,Recursion,我编写了一个如下所示的小程序,它计算一个无限递归循环在导致StackOverflow错误之前将执行多少次 public class Testing { static void p(int i) { System.out.println("hello" + i); i++; p(i); } public static void main(String[] args) { p(1); } } 问题是,它

我编写了一个如下所示的小程序,它计算一个无限递归循环在导致StackOverflow错误之前将执行多少次

public class Testing {
    static void p(int i) {
        System.out.println("hello" + i);
        i++;
        p(i);
    }
    public static void main(String[] args) {
        p(1);
    }
}
问题是,它每次都会在不同的数字上出错,通常在8000到9000之间。有人能解释为什么会这样吗


编辑:我正在使用EclipseIDE,还没有用其他IDE或命令行测试过它。

StackOverflowerError当堆栈(存储方法执行堆栈的内存部分)与堆(分配对象、原语等的内存)冲突时抛出。您无法预测何时抛出错误,因为堆栈的大小可以是动态的,除非由
-Xss
标志指定。这就是为什么没有固定的方法执行深度,这导致
StackOverflowerError

可能与计算机可以分配给程序的实际内存量有关,而其他程序和进程正在计算机中运行StackOverflower错误。作为一个错误,与JVM相关(错误不是例外!)

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


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

因此,正如其他人指出的那样,您可能需要了解使用了什么JVM,从那里了解垃圾收集器(调用gc的频率)也是一个很好的练习正在使用,因为这不仅可以让您更深入地了解堆栈溢出错误,还可以让您更深入地了解Java的一般工作方式。如果你真的很热心,你可以实现你自己的小型JVM,并且可能有一个更好的方案

JVM规范很好地解释了它与堆栈相关的行为

每个Java虚拟机线程都有一个私有Java虚拟机 堆栈,与线程同时创建。Java虚拟机 堆栈存储帧(§2.6)。Java虚拟机堆栈与此类似 对于C等常规语言的堆栈:它保存本地 变量和部分结果,并在方法调用中发挥作用 然后返回。因为Java虚拟机堆栈从来都不是 除了推送和弹出帧之外,帧可以被直接操纵 分配。Java虚拟机堆栈的内存不需要 相邻

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

该规范允许Java虚拟机堆栈 一个固定的大小或大小,可以根据 计算。如果Java虚拟机堆栈的大小固定, 可以选择每个Java虚拟机堆栈的大小 在创建堆栈时独立运行

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

以下异常情况与Java虚拟机相关 机器堆栈:

如果线程中的计算需要更大的Java虚拟机 如果堆栈超出允许范围,Java虚拟机将抛出 堆栈溢出错误

是否可以动态扩展Java虚拟机堆栈,以及 已尝试扩展,但可用内存不足 进行扩展,或者如果内存不足 可用于为新服务器创建初始Java虚拟机堆栈 线程时,Java虚拟机抛出OutOfMemoryError

就你的问题而言,这段摘录中的一个要点是:

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

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

如果使用-Xss命令行参数设置堆栈大小,这个数是否会发生变化?这是非常错误的,不会与任何内容发生冲突。OP程序的堆栈空间不足,堆栈空间有一个默认值,可以通过
-Xss
命令行显式设置option@DavidSoroko这里有一个可笑的解释:。然而Op并没有在没有参考其他答案的情况下设置堆栈大小,所以,您能解释一下“堆栈与堆冲突”的实际含义吗?在阅读了关于
-Xss
的文档后,请重新阅读您的“您无法预测…”备注。@DavidSoroko editedIn OpenJDK(大概是Oracle)JVM实现,如果没有明确提供堆栈大小,则将其设置为默认值:
java-XX:+PrintFlagsFinal | grep“ThreadStackSize”运行
java-Xss2m-XX:+PrintFlagsFinal | grep“ThreadStackSize”
products
ThreadStackSize=1024