System.gc与finalize以及Thread对象何时被回收

System.gc()建议JVM进行一次垃圾回收。垃圾对象在被回收之前,其finalize方法会被JVM自动调用,用于做一些清除工作。简单地说,调用了System.gc()之后,java在内存回收过程中就会调用那些要被回收的对象的 finalize() 方法。

下面看一个例子。

User:

package com.zzj.gc;

public class User {
	private String name;
	
	public User(String name) {
		this.name = name;
	}
	
	@Override
	protected void finalize() throws Throwable {
		System.out.println("User " + name +" finalize");
	}
}
MyThread:
package com.zzj.gc;

public class MyThread extends Thread {
	private String name;
	
	public MyThread(String name) {
		this.name = name;
	}

	@Override
	public void run() {
		try {
			Thread.sleep(6 * 1000);
		} catch (InterruptedException e) {
			Thread.currentThread().interrupt();
			e.printStackTrace();
		}
	}
	
	@Override
	protected void finalize() throws Throwable {
		System.out.println(name + " finalize");
	}
}
Test:
package com.zzj.gc;

public class Test {
	public static void main(String[] args) throws Exception {
		new User("Jim");
		
		new MyThread("myThread").start();
		
		System.gc(); // Jim将被回收
		
		Thread.sleep(9 * 1000); // 等待线程myThread执行完毕
		
		System.gc(); // myThread线程对象将被回收
		
		Thread.sleep(3 * 1000);
	}
}
输出:
User Jim finalize
myThread finalize
第一次调用System.gc()后,线程对象myThread并不会被立即回收,只有等待线程执行完毕,再次调用System.gc()后才会被回收。

当然我们也可以不调用System.gc(),而是创建大量的对象,这样垃圾回收器也会执行GC。

之所以要有finalize( ),是由于你可能在分配内存时,采用了类似C语言中的做法而非Java中的通常做法。这种情况主要发生在使用“本地方法”的情况下,它是在Java中调用非Java代码的一种方式。本地方法目前只支持C和C++。但它们可以调用其它语言写的代码,所以你实际上可以调用任何代码。在非Java代码中,也许会调用类似C的malloc( )函数,用它分配存储空间,而且除非调用了free( )函数,否则存储空间将不会得到释放,从而造成内存泄露。当然,free( )是C和C++中的函数,所以你需要在finalize( )中用本地方法调用它。




你可能感兴趣的:(Java虚拟机)