java 垃圾回收概述

2020-09-18

java对象被GC宣告死亡之前至少要经历两次标记过程。

概述

在java对象被GC宣告死亡之前至少要经历两次标记过程,如果对象没有与GC Roots相连的引用链(这里使用的算法是可达性分析算法),第二次就是是否调用对象的finalize(),如果调用了,并且在finalize()方法里面对象重新获取了GC Roots的引用,那么对象依旧可以存活下去,否则将会被清除。

1.第一次标记

当JVM触发一次 minor GC(这里具体指的是针对java堆新生代的垃圾回收,因为在有的虚拟机里有可能对方法区进行垃圾回收)时,如果对象在此时没有与GC Roots的引用链,那么对象就会第一次被标记,可作为GC Roots大概如下几种:

1.虚拟机栈引用的对象。 2.方法区中静态属性引用的对象。 3.方法区中常量引用的对象。 4.本地方法栈中Native方法引用的对象。 5.JVM内部引用,如基本数据类型对应的Class对象,一些常驻的异常对象,还有系统类加载器。 6.所以被同步锁(synchronized关键字)持有的对象。 7.反映Java虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等。

2.第二次标记

在第二次标记的时候,对象只有一次机会可以逃脱被清除的命运,就是程序员重写了finalized()方法、并且是这个对象第一次触发GC,并且finalized()方法内部为这个对象重新获取了GC Roots的引用。所以如果想要一个被GC标记了的对象不被清除,可以重写当前对象的finalized()方法(注意:只有第一次触发GC才会调用此方法,第二次不会调用)

演示代码如下(代码为《深入理解java虚拟机》代码清单3-2)
/**
 * 此代码演示了两点:
 * 1.对象可以在被GC时自我拯救。
 * 2.这种自救的机会只有一次,因为一个对象的finalize()方法最多只会被系统自动调用一次
 *
 * @author zzm
 */
public class FinalizeEscapeGC {

    public static FinalizeEscapeGC SAVE_HOOK = null;

    public void isAlive() {
        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 Throwable {
        SAVE_HOOK = new FinalizeEscapeGC();

        //对象第一次成功拯救自己
        SAVE_HOOK = null;
        System.gc();
        // 因为Finalizer方法优先级很低,暂停0.5秒,以等待它
        Thread.sleep(500);
        if (SAVE_HOOK != null) {
            SAVE_HOOK.isAlive();
        } else {
            System.out.println("no, i am dead :(");
        }

        // 下面这段代码与上面的完全相同,但是这次自救却失败了
        SAVE_HOOK = null;
        System.gc();
        // 因为Finalizer方法优先级很低,暂停0.5秒,以等待它
        Thread.sleep(500);
        if (SAVE_HOOK != null) {
            SAVE_HOOK.isAlive();
        } else {
            System.out.println("no, i am dead :(");
        }
    }
}

#####结果:

finalize method executed!
yes, i am still alive :)
no, i am dead :(

本文参考了周志明大大的《深入理解java虚拟机》第三版,特此说明