finalize() 方法
对象的回收需要经历两次标记过程:如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那么它将会被第一次标记并且进行一次筛选,筛选的条件就是此对象是否有必要执行finalize() 方法。当对象没有覆盖finalize() 方法,或者finalize() 方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。
如果这个对象被判定为有必要执行finalize() 方法,那么这个对象将会放置一个叫做F-Queue的队列之中,并在稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去执行它。finalize() 方法是对象逃脱被回收的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize() 方法中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可,比如把自己赋值给某个类变量或者对象的成员变量,那么第二次标记时它将被移除出“即将回收”的集合;如果对象这时候还没有逃脱,那基本上它就真的被回收了。
举个例子
public class FinalizeEscapeGC {
public static FinalizeEscapeGC save_hook = null;
public void isSave() {
System.out.println("yes, i am still alive :)");
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize method executed!");
FinalizeEscapeGC.save_hook = this;
}
public static void main(String[] args) throws InterruptedException {
save_hook = new FinalizeEscapeGC();
save_hook = null;
System.gc();
Thread.sleep(500);
if (save_hook != null) {
save_hook.isSave();
} else {
System.out.println("no, i am dead :(");
}
save_hook = null;
System.gc();
Thread.sleep(500);
if (save_hook != null) {
save_hook.isSave();
} else {
System.out.println("no, i am dead :(");
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
输出结果为:
finalize method executed!
yes, i am still alive :)
no, i am dead :(
1
2
3
从输出结果可以看出finalize() 方法被执行,第一次GC后它仍然可以存活,第二次GC后它被回收,这是因为finalize() 方法只会被系统自动调用一次。
---------------------
转载,仅作分享,侵删
作者:EagleLi1
原文:https://blog.csdn.net/qq_21687635/article/details/83832542
|
|