我们都知道,Java的内存清理是通过垃圾回收器进行的,那么其是如何将没用的对象被被清理掉的呢。

其实当垃圾回收器准备回收对象内存的时候,首先会调用对象的finalize()方法,并且在下一次垃圾回收动作发生的时候真正回收对象的内存,所以在finalize()中你可以会一些必要的清理工作

那么问题又来了,finalize()是个什么鬼呀,既然会调用对象的这个方法就说明所有的类都会有这个方法(毕竟所有的类都会被回收嘛),自然而然我们就想到了java的根类 Object.进去看看

protected void finalize() throws Throwable { }

最后一行还真找到了,是一个实现为空的方法,既然是protected就说明具体的方法可以留给子类去实现

之前我们说过只有当对象不再被任何引用指向时候,该对象才会被回收。那么真的是这样吗?我们举个栗子看看

public class User {
private int money;
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
public void cool(){
String str=new String();
}
@Override
protected void finalize() throws Throwable {
// TODO Auto-generated method stub
if(money>0){
System.out.println("error");
}
else{
System.out.println("suceess");
}
super.finalize();
}
}

这里我们重写finalize()方法,在销毁前如果一个人的前还没花光,打印这个人是失败的,否则这个人是成功的。

我们在main()中的代码

public class Test {
public static void main(String args[]){
User u1=new User(200);
new Object();
new User(100);
}
}

运行一下,结果如下:

居然什么都没有!运行结束之后不光有引用指向的u1,就连没有任何引用指向的new User(100);居然都没有被回收。这是怎么回事呢?

我们来看看Thinking In Java中是怎样解释的

java中的并非总是被垃圾回收,也就是说对象可能不被回收。一般程序只要不到濒临存储空间用光,垃圾回收器一般都不会主动回收内存,如果程序结束,并且垃圾回收器一直没有释放你创建的空间,则随着程序的退出,资源则会被归还给操作系统。所以上面的我们finalize()才一直没有被调用

如果我们想看到效果,可以通过如下方法:

public class Test {
public static void main(String args[]){
User u1=new User(200);
new Object();
new User(100);
System.gc();
}
}

System.gc();会强制系统垃圾回收器工作,运行效果如下

error

可以看到new User(100);创建的对象被回收了。

至于java的垃圾回收器的具体工作原理,它是如何清理那么已经无法被使用的内存?这里面涉及的东西就很多了,方法也有很多,等我看明白了再详细讲解。