为什么没有OutOfMemoryError

时间:2015-12-25 20:16:22

标签: java heap

我无法理解为什么此代码中没有OutOfMemoryError

public static void main(String[] args) {
    Object[] ref = new Object[1];
    while (true) {
        ref[0] = new Object[]{ref};
        ref = (Object[]) ref[0];
    }
}

至于我,上面提到的代码必须按以下方式工作:

Start:
   ref = new Object[1];
Loop:
   ref[0] = new Object []{ new Object[1] }
   ref = new Object []{ new Object[1] }
   ref[0] = new Object []{ new Object []{ new Object[1] } }
   ref = new Object []{ new Object []{ new Object[1] } }

我的意思是保存每个新Object的链接,垃圾收集器不能删除未使用的对象,因此必须有OutOfMemoryError。但如果代码运行,它将工作年龄......

我不明白或我错在哪里?请解释一下。

2 个答案:

答案 0 :(得分:7)

此处没有内存泄漏。

考虑以下步骤:

  1. Object[] ref = new Object[1];
    记忆:ref --> array 1
  2. ref[0] = new Object[]{ref};
    记忆:ref --> array 1 --> array 2 --> array 1
  3. ref = (Object[]) ref[0];
    记忆:ref --> array 2 --> array 1 --> array 2 --> ...
  4. ref[0] = new Object[]{ref};
    记忆:ref --> array 2 --> array 3 --> array 2 --> ...
    此时,array 1不再被引用,因此可以进行GC收集。
  5. ref = (Object[]) ref[0];
    记忆:ref --> array 3 --> array 2 --> array 3 --> ...
  6. ref[0] = new Object[]{ref};
    记忆:ref --> array 3 --> array 4 --> array 3 --> ...
    此时,array 2不再被引用,因此可以进行GC收集。
  7. ......循环继续。在每个循环之后,有一个不再引用的数组,它有资格进行垃圾回收。只要GC完成其工作,您就永远不会耗尽内存。

    编辑:更正了数组在内存中的链接方式。感谢Javier指出这一点。

答案 1 :(得分:0)

用你自己的假设来解释,

Start:
   ref = new Object[1];
Loop:
   ref[0] = new Object []{ new Object[1] }
   ref = new Object []{ new Object[1] }
   // at this point ref is re-allocated
   ref[0] = new Object []{ new Object []{ new Object[1] } }
   ref = new Object []{ new Object []{ new Object[1] } }
   // at this point ref is re-allocated

上述两个点ref正在重新分配,因此先前ref的引用将丢失。由于ref丢失,这意味着java垃圾收集器已准备好取消引用前一个ref指向的内存。

因此代码中没有内存泄漏