java - 迭代构造函数内存困惑

标签 java recursion memory stack-overflow heap-memory

我是来写下面代码的:

public class foo {

    static int iterationCounter = 0;

    public foo() {
        iterationCounter++;
        System.out.println(iterationCounter);
        new foo();

    }

    public static void main(String[] args) {
        new foo();

    }


}

在 StackOverflow Exception 产生之前,由值 iterationCounter 组成的最后一个日志是:11472,因此 Java 预留了 x 数量用于创建 11472 foo 对象的内存。

但是下面的代码输出了一个与其他程序不同的日志:

public class foo {

    static int iterationCounter = 0;
    foo fooObject;

    public foo() {
        iterationCounter++;
        System.out.println(iterationCounter);
        this.fooObject = new foo();

    }

    public static void main(String[] args) {
        new foo();

    }


}

这是我对内存管理的困惑。我以为iterationCounter的值会和其他程序一样,结果这次是9706。由于 fooObject 是一个公共(public)变量(一个字段),它应该存储在堆内存中(不是吗?)而不是堆栈内存中。如果是这种情况,它不应该占用堆栈空间(或者将所有新创建的 fooObjects 及其所有属性存储在堆栈中)?

最佳答案

第一个版本生成以下代码(javap -c ... 的输出):

   ...                                     
   18:  invokevirtual   #4; //Method java/io/PrintStream.println:(I)V            
   21:  new     #5; //class Test                                                 
   24:  dup                                                                      
   25:  invokespecial   #6; //Method "<init>":()V                                
   28:  pop                                                                      
   29:  return          

第二个 - 如下:

   ...                                       
   18:  invokevirtual   #4; //Method java/io/PrintStream.println:(I)V                 
   21:  aload_0                                                                       
   22:  new     #5; //class Test                                                      
   25:  dup                                                                           
   26:  invokespecial   #6; //Method "<init>":()V                                     
   29:  putfield        #7; //Field test:LTest;                                       
   32:  return 

如您所见,递归调用之前这些 list 之间的唯一区别是第二个 list 中第 21 行的 aload_0

该操作将局部变量0(它是this)的值加载到堆栈上,以便以后可以将其用作putfield 的对象引用。手术。

因此,您观察到的差异是由每次调用在堆栈上存在一个额外条目引起的 - 用于将值写入字段的 this 引用。

关于java - 迭代构造函数内存困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12353256/

相关文章:

java - 将 JButton 控件添加到 JApplet 并且 JButton 填满整个屏幕

java - 了解模型解析的工作原理

java - 在 Hadoop 上运行 MapReduce 字数统计会给出异常消息 : The system cannot find the path specified

java - Spring jdbc 不适用于 h2 查询递归

java - 递归方法在返回值后继续?

c++ - 如果知道变量地址,如何在 C++ 中检索变量值

android - 当调用 putExtra() 时内存方面会发生什么?

java - 与线程模式混淆

c++ - gcc 是否优化递归函数?怎么做?

javascript - 可能的node.js内存过度使用w/express服务器和pm2