ITEEDU

Java Gossip: 垃圾回收

在C++中,使用new配置的对象,必须使用delete来 清除对象,以释放对象所占据的内存空间,如果没有进行这个动作,则若对象不断的产生,内存就会不断的被耗用,最后使得内存空间用尽,然而使用 delete并不是那么的简单,如果不小心清除了尚被参考的对象,或是对象间共享的资源,则程序就会发生错误,小心的使用new与delete,一直是C ++中一个重要的课题。

在Java中,使用new配置的对象,基本上也是必须清除以回收内存空间的,但是您并不用特别关心这个问题,因为Java提供「垃圾收集」(Garbage collection)机制,在适当的时候,Java执行环境会自动检查对象,看看是否有未被参考的对象,如果有的话就清除对象、回收对象所占据的内存空间。

垃圾收集的时机我们并无法得知,可能是内存资源不足的时候,或是在程序空闲的时候,您可以建议执行环境进行垃圾收集,但也仅止于建议,如果程序当时有优先权更高的执行绪(Thread)正在进行,则垃圾收集并不一定会马上进行。

在C++中有解构方法(Destructor),它会在对象被清除前执行,在Java中并不明确有解构方法,因为我们不知道对象什么时候会被回收,在Java中有finalize()这 个方法,它被宣告为protected,它会在对象被回收时执行,但您不可以将它当作解构方法来使用,因为不知道对象资源何时被回收,所以也就不会立即执 行我们所指定的动作,但您可以使用finalize()来进行一些相关资源的清除动作,而这些动作与立即性的收尾动作并没有关系。

如果我们确定某个对象不再使用,您可以在参考至该对象的名称上指定null,表示这个名称不在参考至任何对象,可以使用System.gc()建议程序进行垃圾收集,如果建议被采纳,则对象资源会被回收,回收前会执行finalize()方法。

下面这个程序是个简单的示范:

GcTest.java
public class GcTest {
	private String name;
	public GcTest(String name) {
		this.name = name;
		System.out.println(name + "建立");
	}
	// 对象回收前执行
	protected void finalize() {
		System.out.println(name + "被回收");
	}
}
UseGC.java
public class UseGC {
	public static void main(String[] args) {
		System.out.println("请按Ctrl + C终止........");
		GcTest obj1 = new GcTest("object1");
		GcTest obj2 = new GcTest("object2");
		GcTest obj3 = new GcTest("object3");
		// 令名称不参考至对象
		obj1 = null;
		obj2 = null;
		obj3 = null;
		// 建议回收对象
		System.gc();
		while(true); // 不断执行program
	}
}

执行结果:

请按Ctrl + C终止........ 
object1建立 
object2建立 
object3建立 
object1被回收 
object2被回收 
object3被回收?

您故意加上无穷循环,以让垃圾收集在程序结束前有机会执行,藉以了解垃圾收集确实会运作。