GC(3)、Java对象回收概述
一、被可达性分析或者引用计数法标记为无用对象后就一定会被GC回收掉吗?
二、答案(纯文字,希望大家好好读,通俗易懂,很关键)
当然不是!!!!
一个对象的死亡至少要经历两次标记过程:
如果对象被标记为可回收对象,那他将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法,当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行回收”。(这也是为什么大家不鼓励重写finalize方法的原因之一)
如果对象被判定为有必要执行finalize()方法,那么这个对象会放到一个叫做F-Queue队列中,并在稍后一个由虚拟机自动建立的、低优先级的Finalizer线程去执行它,这里的执行只是负责触发这个方法,并不一定等这个方法执行结束。这样做的原因是如果一个对象在finalize()方法中执行缓慢,或者发生了死循环,将很可能导致F-Queue队列中其他对象处于永久等待,甚至整个内存回收系统崩溃。
finalize()方法是对象逃脱死亡命运的最后你一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize()中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可(这里描述的是可达性分析算法,因为虚拟机几乎都不采取引用计数法)。譬如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那么在第二次标记时他将被移除出“即将回收”的队列;若对象这时候还没有逃脱,那么基本上真的就要被回收了。
三、用代码证明上面的答案
/**
* 1、对象在被GC时候可以有一次自我挽救的机会
* 2、这种自救的机会只有一次,因为一个对象的finalize方法最多只能被系统自动调用1次
*
* @author TongWei.Chen 2017-09-05 14:49:04
*/
public class FinalizeEscapeGC {
public static FinalizeEscapeGC SAVE_HOOK = null;
public void isAlive() {
System.out.println("我还活着呢....");
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize方法执行了....");
FinalizeEscapeGC.SAVE_HOOK = this;
}
public static void main(String[] args) throws InterruptedException {
SAVE_HOOK = new FinalizeEscapeGC();
//对象第一次成功拯救自己
SAVE_HOOK = null;
//督促垃圾收集器工作
System.gc();
//因为finalize方法优先级很低,所以暂停1s以等待它
Thread.sleep(1000);
if(SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
} else {
System.out.println("我已经死了....");
}
//下面这段代码与上面的完全相同,但是这次自救却失败了。
//对象第二次成功拯救自己
SAVE_HOOK = null;
System.gc();
//因为finalize方法优先级很低,所以暂停1s以等待它
Thread.sleep(1000);
if(SAVE_HOOK != null) {
SAVE_HOOK.isAlive();
} else {
System.out.println("我已经死了....");
}
}
}
结果
finalize方法执行了....
我还活着呢....
我已经死了....
四、回收方法区
GC回收的不只是堆内存,还有方法区!!!
永久代(方法区)的垃圾收集主要回收两部分内容:废弃常量和无用的类。
判定一个常量是否是“废弃常量”很简单:
比如
String str = "abc";
abc在常量池中,但是现在str = null;不在引用abc这个常量了,那么这是发生内存回收的话,就会把abc清除常量池。
判定一个类是否是“无用的类”很麻烦:
1、该类所有的对象都已经回收,也就是Java堆中不存在该类的任何对象。
2、加载该类的ClassLoader已经被回收。
3、该类对应的Class对象没有在任何地方被引用,无法再任何地方通过反射访问该类的方法。
若有兴趣,欢迎来加入群,【Java初学者学习交流群】:458430385,此群有Java开发人员、UI设计人员和前端工程师。有问必答,共同探讨学习,一起进步!
欢迎关注我的微信公众号【Java码农社区】,会定时推送各种干货:
![](https://img.haomeiwen.com/i4582242/ca4a357ae859b1aa.jpg)