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

标签 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);
    }
}

问题是,它每次都在不同的数字上出错,通常在 8000 到 9000 之间。谁能解释为什么会这样?

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

最佳答案

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

Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. A Java Virtual Machine stack stores frames (§2.6). A Java Virtual Machine stack is analogous to the stack of a conventional language such as C: it holds local variables and partial results, and plays a part in method invocation and return. Because the Java Virtual Machine stack is never manipulated directly except to push and pop frames, frames may be heap allocated. The memory for a Java Virtual Machine stack does not need to be contiguous.

In the First Edition of The Java® Virtual Machine Specification, the Java Virtual Machine stack was known as the Java stack.

This specification permits Java Virtual Machine stacks either to be of a fixed size or to dynamically expand and contract as required by the computation. If the Java Virtual Machine stacks are of a fixed size, the size of each Java Virtual Machine stack may be chosen independently when that stack is created.

A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of Java Virtual Machine stacks, as well as, in the case of dynamically expanding or contracting Java Virtual Machine stacks, control over the maximum and minimum sizes.

The following exceptional conditions are associated with Java Virtual Machine stacks:

If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a StackOverflowError.

If Java Virtual Machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java Virtual Machine stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

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

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

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

关于java - 为什么递归函数会停止在随机数上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55108159/

相关文章:

java - 编写我自己的包装器类并声明其元素数组

java - Java中未知类型的排序列表

C++归纳算法非常慢和动态编程

python - 使用递归回溯生成集合的所有子集 (Python)

scala - AST 转换对象如何工作?

java - 学习递归,调用类时出错

java - Hadoop中的MapReduce程序,实现了一个简单的 “People You Might Know”

java - 如何给自定义对象添加ActionListener

c++ - 打印链表元素

python - SQLAlchemy 递归