java基础之强引用

强引用介绍

强引用就是我们普遍使用一个对象时的方法,即类似Object obj=new Object()这种的引用方法。在强引用时,JVM即使内存溢出,抛出OutOfMemoryError错误,使程序运行中断,也不会去回收强引用对象解决内存溢出问题。因此在强引用对象用完时需要将强引用弱化,可将对象置为空obj=null

也就是说,我们平常进行操作的都是强引用对象。并且这部分对象都有指向内存中的一个地址,那么永远不会被回收。

demo演示

创建一个对象,并且重写Object中的finalize方法

public class M {

    // 当GC在确定该对象不被引用后,就会调用这个方法,并且只会调用这个对象的这个方法,有且只有一次。
    // 执行该方法后,该对象就会被丢弃
    @Override
    protected void finalize() {
        System.out.println("finalize");
    }

}

演示

public class Test {

    public static void main(String[] args) throws IOException {
        // 创建一个强引用对象
        M m = new M();
        // 若指向null,则会被垃圾回收器不定时回收
        m = null;

        // 主动调用gc回收对象
        System.gc();
        System.out.println(m);

        // 阻塞主进程,可以更加清晰的查看调用finalize的过程
        // 因为GC并不是使用主进程执行的,而是通过子进程执行,
        // 如果不阻塞的话,就有可能看不到调用finalize,就会直接被结束
        System.in.read();
    }
}

finalize

FinalReference访问权限为package,并且只有一个子类Finalizer,同时Finalizer 是final修饰的类,所以无法继承扩展。

与Finalizer相关联的则是Object中的finalize()方法,在类加载的过程中,如果当前类有覆写finalize()方法,则其对象会被标记为finalizer类,这种类型的对象被回收前会先调用其finalize()。

具体的实现机制是,在gc进行可达性分析的时候,如果当前对象是finalizer类型的对象,并且本身不可达(与GC Roots无相连接的引用),则会被加入到一个ReferenceQueue类型的队列(F-Queue)中。而系统在初始化的过程中,会启动一个FinalizerThread实例的守护线程(线程名Finalizer),该线程会不断消费F-Queue中的对象,并执行其finalize()方法(runFinalizer),并且runFinalizer方法会捕获Throwable级别的异常,也就是说finalize()方法的异常不会导致FinalizerThread运行中断退出。对象在执行finalize()方法后,只是断开了与Finalizer的关联,并不意味着会立即被回收,还是要等待下一次GC,而每个对象的finalize()方法都只会执行一次,不会重复执行。

posted @ 2023-06-07 22:46  King-DA  阅读(167)  评论(0)    收藏  举报