2013-04-07 123 views
0

那么,我正在经历Java中的内存泄漏。为什么这个程序会导致内存泄漏?

我看到这个简单的程序如下这里笔者说, 内存泄漏可能与此计划之下

但是能告诉我什么是错用此程序,以及为什么它可以 产生内存泄漏?

package com.code.revisited.memoryleaks; 


public class StackTest { 

    public static void main(String[] args) { 
     Stack<Integer> s = new Stack<>(10000); 
     for (int i = 0; i < 10000; i++) { 
      s.push(i); 
     } 

     while (!s.isEmpty()) { 
      s.pop(); 
     } 

     while(true){ 
      //do something 
     } 

    } 

} 
+1

这可能是因为堆栈仍然会占用一些位置,但这不是真正的“泄漏”。 – 2013-04-07 17:38:26

+0

这不是内存泄漏。我想理想的情况是'Stack'会进入一个范围,当你完成它时它可以被GC'd,但这不是一个“泄漏”。 – 2013-04-07 17:39:05

+1

如果你指的是http://coderevisited.com/memory-leaks-in-java/,那么泄漏不在这个例子中,而是在'Stack.pop'中。这部分是好的。 – zch 2013-04-07 17:41:27

回答

1

这实际上取决于堆栈的实现方式。

如果这是Java的堆栈(java.util.Stack),那么它不应该发生。底层数组是动态的,可能有未使用的插槽,但是在弹出项目时显式设置为空。

我猜你的例子中的堆栈不是标准堆栈;这可能是该示例的一部分,它说明了这种内存泄漏。例如,如果pop()方法减少底层数组索引,但不将数组项设置为空,那么上面的代码应该在堆中留下1000个活动对象,尽管程序可能不再需要它们。

- 编辑 -

你接受来自http://coderevisited.com/memory-leaks-in-java/的例子吗? 如果是这样,请注意,它也包含堆栈实现,就像我怀疑的那样。

+0

是的,我从那里拿了一个例子,但我想产生内存泄漏。 – Kiran 2013-04-07 17:58:27

+0

@Kiran:假设你依赖一个数组arr,并且你的当前顶部索引用j表示,你的pop方法可能应该做如下操作:1)检查堆栈是否为空2)用值arr保存一个引用[j] 3)给arr [j]分配null 4)返回参考 – 2013-04-07 17:59:39

+0

明白了,非常感谢。 – Kiran 2013-04-07 18:00:33

1

pop方法是从Stack除去Integer对象。但是Integer对象没有被去引用。这意味着他们将占据记忆。

更新

这一点在Item 6 of Effective Java解释说:淘汰落后对象引用

If a stack grows and then shrinks, the objects that were popped off the stack will not be garbage collected, even if the program using the stack has no more references to them. This is because the stack maintains obsolete references to these objects. An obsolete reference is simply a reference that will never be dereferenced again.

的修复为这类问题很简单:空出来的引用或删除对象一旦它们变得过时,它们就会从Stack上移除在给定的情况下,弹出方法会减少顶部参考。

+0

你是指第256个?或者是什么 ? – 2013-04-07 17:37:56

+1

这并没有什么意义,因为Java文档说它会从栈顶移除整数。所以解引用并不是必须的。但我从来没有使用'堆栈',所以请详细说明,这样我就可以理解:) – Andy 2013-04-07 17:41:16

+0

我认为和安迪一样,为什么需要解引用? – Kiran 2013-04-07 17:42:34