假设我在java中实现了一个队列,我有一个名为ini的初始节点的引用,另一个名为last的引用.现在,我开始将对象插入队列.有一次,我决定要一个清除队列的操作.然后我这样做:
ini = null; last = null;
我是否泄漏记忆?ini和last之间的节点都是链接的,我猜仍然有它们的数据,但同时还有垃圾收集器.
另一种方法是访问每个元素,然后将它们对下一个节点的引用置空,但是我基本上就像在C++中那样,除了我不会明确地使用delete.
只要代码中的任何其他位置都没有引用队列中的项,垃圾回收器就能够回收该内存.在Java中将指针设置为null与C中的指针不同,其中将malloc指定的null设置为阻止它被释放.在Java中,当内存不再可访问时,内存将被回收.只要您没有通过JNI使用本机代码,Java中就没有内存泄漏(在C/C++意义上).
一个简单的垃圾收集器只计算一个对象的引用数,并在引用计数达到零时解除分配该对象,但是这将无法处理引用循环(A - > B,A - > B - > C - > A等).Java GC算法进行活性测试,在这里他们构建系统中所有对象的参考图.GC执行图遍历,任何无法访问的节点(对象)都标记为未使用且可用于重新分配.图的根(遍历的起始行)包括线程堆栈上的变量,静态变量和本机代码通过JNI持有的引用.在此处查看更多信息:http://java.sun.com/developer/Books/performance/performance2/appendixa.pdf
仍然可能存在参考泄漏.这指的是您持续对对象的引用超过所需时间的情况.例如:
public class Stack { private final Object[] stack = new Object[10]; private int top = 0; public void push(Object obj) {stack[top++] = obj;} public Object pop() {return stack[top--]; } }
忽略溢出/下溢的可能性,在调用Stack.pop()之后,数组成员变量仍然具有对返回的对象的引用.它将阻止该对象被垃圾收集,直到不再引用周围的Stack实例.这是极少数情况之一,需要将变量设置为null,以便可以回收其内存:
public Object pop() {Object ret = stack[top]; stack[top--] = null; return ret;}