垃圾清理势在必行——Java垃圾收集算法
http://tech.ddvip.com 2007年09月14日 社区交流
内容摘要:垃圾收集算法的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。
5.Java 内存泄漏
由于采用了垃圾回收机制,任何不可达对象(对象不再被引用)都可以由垃圾收集线程回收。因此通常说的Java 内存泄漏其实是指无意识的、非故意的对象引用,或者无意识的对象保持。无意识的对象引用是指代码的开发人员本来已经对对象使用完毕,却因为编码的错误而意外地保存了对该对象的引用(这个引用的存在并不是编码人员的主观意愿),从而使得该对象一直无法被垃圾回收器回收掉,这种本来以为可以释放掉的却最终未能被释放的空间可以认为是被“泄漏了”。
考虑下面的程序,在ObjStack类中,使用push和pop方法来管理堆栈中的对象。两个方法中的索引(index)用于指示堆栈中下一个可用位置。push方法存储对新对象的引用并增加索引值,而pop方法减小索引值并返回堆栈最上面的元素。在main方法中,创建了容量为64的栈,并64次调用push方法向它添加对象,此时index的值为64,随后又32次调用pop方法,则index的值变为32,出栈意味着在堆栈中的空间应该被收集。但事实上,pop方法只是减小了索引值,堆栈仍然保持着对那些对象的引用。故32个无用对象不会被GC回收,造成了内存渗漏。
以下是引用片段:
public class ObjStack {
private Object[] stack;
private int index;
ObjStack(int indexcount) {
stack = new Object[indexcount];
index = 0;
}
public void push(Object obj) {
stack[index] = obj;
index++;
}
public Object pop() {
index--;
return stack[index];
}
}
public class Pushpop {
public static void main(String[] args) {
int i = 0;
Object tempobj;
ObjStack stack1 = new ObjStack(64);
/** new一个ObjStack对象,并调用有参构造函数。分配stack Obj数组的
* 空间大小为64,可以存64个对象,从0开始存储。
*/
while (i < 64)
{
tempobj = new Object();
//循环new Obj对象,把每次循环的对象一一存放在stack Obj数组中。
stack1.push(tempobj);
i++;
System.out.println("第" + i + "次进栈" + " ");
}
while (i > 32)
{
tempobj = stack1.pop();//这里造成了空间的浪费。
/**正确的pop方法可改成如下所指示,当引用被返回后,
*堆栈删除对他们的引用,因此垃圾收集器在以后可以回收他们。
*/
/**
* public Object pop() {
* index - -;
* Object temp = stack [index];
* stack [index]=null;return temp;
* }
*/
i--;
System.out.println("第" + (64 - i) + "次出栈" + " ");
}
}
}
责编:豆豆技术应用