java运行过程中产生的垃圾内存是不需要我们处理的,由垃圾回收器自动回收,我们也可以调用System中的gc()方法,通知垃圾回收器启动回收机制,但是垃圾回收器回收什么
样的内存呢?让我们通过几个程序来判断一下。
第一个例子:
public class Test1 {
public static void main(String[] args) {
test();
System.gc();
System.out.println( "main....." );
}
public static void test() {
AA aa = new AA();
BB bb = new BB();
}
}
class AA {
@Override
protected void finalize() throws Throwable {
System.out.println( "AA 被回收" );
}
}
class BB {
@Override
protected void finalize() throws Throwable {
System.out.println( "BB 被回收" );
}
}
很明显,在这个例子中,“AA被回收”和“BB被回收”都能够打印出来,因为在test方法中有两个引用,aa和bb,分别指向堆中的两块内存,当test方法执行完毕后,弹栈,引用也
随之失效,两块内存也成为了没用引用指向的内存空间,成为了无用内存,此时通知GC回收,会把两块垃圾内存回收掉。我们再看下一个例子:
public class Test2 {
public static void main(String[] args) {
test();
System.gc();
System.out.println( "main....." );
}
public static void test() {
AA aa = new AA();
BB bb = new BB();
aa.b = bb;
bb.a = aa;
}
}
class AA {
public BB b;
@Override
protected void finalize() throws Throwable {
System.out.println( "AA 被回收" );
}
}
class BB {
public AA a;
@Override
protected void finalize() throws Throwable {
System.out.println( "BB 被回收" );
}
}
这个例子和上一个很像,只不过在aa引用指向的内存空间里还有一个引用指向bb引用指向的内存空间,同样,在bb引用指向的内存空间里还有一个引用指向aa引用指向的内存
空间,说起来好像有点绕,我们看一下这个例子的内存机构图:
大家可以清楚地看到内存的运行机制,当test方法执行完毕后,弹栈的时候,堆区中AA对象内存空间和BB对象内存空间还有彼此的引用指向。此时,如果通知垃圾回收器回收
垃圾内存的话,这两块内存空间会被回收吗?答案是会的,因为java中定义无用的对象是这样定义的:当堆内存中的对象没有堆以外的引用指向的时候,那么这个对象就成为了
无用的对象,就会被垃圾回收器回收。所以上面的例子符合java中垃圾回收机制,所以一定会被回收。