垃圾清理势在必行——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) + "次出栈" + "  ");
  }
  }
  }

责编:豆豆技术应用

正在加载评论...