强引用、软引用、弱引用、虚引用用法

强引用、软引用、弱引用、虚引用用法

强引用

强引用是指程序中在程序代码之中类似“Object obj = new Object()”的引用关系,无论任何情况下,只要强引用关系还存在,垃圾回收器就不会回收掉被引用的对象。
强引用是我们最常用的引用,没什么好讲的,在集合源码中也可以见到将强引用置为null来使对象被回收的操作:

    /**
     * HashMap中的清除方法,将所有节点遍历置为null
     * 使不可达对象在下次gc时被回收
     */
    public void clear() {
        Node<K,V>[] tab;
        modCount++;
        if ((tab = table) != null && size > 0) {
            size = 0;
            for (int i = 0; i < tab.length; ++i)
                tab[i] = null;
        }
    }

弱引用

在虚拟机抛出OutOfMemoryError之前,所有对软可达对象的软引用都保证已被清除。也就是说在发生内存溢出之前会先清除软引用,并且软引用对象也会被清除。
这样我们就可以利用软引用做一层缓存,在空间充足的时候保存一些文件,在空间紧张时自动清理并且做一些善后操作。


public class test {
    public static void main(String[] args) {
        softReferenceOverHeadLimitResolve();
    }
    private static void softReferenceOverHeadLimitResolve() {
        int capacity = 1024 * 1024;
        //用来保存对象
        HashSet<SoftReference<SmallSoftObject>> set = new HashSet<>(capacity);
        // 引用队列,被清除的软引用会进入这个队列中,这个队列我们之后还会再用到
        ReferenceQueue<SmallSoftObject> referenceQueue = new ReferenceQueue<>();
        for (int i = 0; i < capacity; i++) {
        	// 保存文件
            set.add(new SoftReference<>(new SmallSoftObject(), referenceQueue));
            // 如果之前保存的文件因为空间不足被清理,可以在这个方法里执行善后处理
            removeObject(set, referenceQueue);
        }
        System.out.println("End");
    }

    private static void removeObject(HashSet<SoftReference<SmallSoftObject>> set, ReferenceQueue<SmallSoftObject> referenceQueue) {
    	//获得被清理的软引用,在set中删除
        Reference<? extends SmallSoftObject> poll = referenceQueue.poll();
        while (poll != null) {
            set.remove(poll);
            poll = referenceQueue.poll();
        }
    }

    static class SmallSoftObject {
        byte[] data = new byte[1024];
    }
}

现在我们添加运行参数,修改堆大小模拟内存不够的情况,并开启gc日志

-Xmx40m -XX:+PrintGC

在这里插入图片描述
以下是运行结果
在这里插入图片描述

弱引用

弱引用在下次垃圾回收发生时就会被回收。

WeakReference<byte[]> wk = new WeakReference<byte[]>(new byte[1024 * 1024 * 100]);
        System.out.println(wk.get());
        System.gc();
        System.out.println(wk.get());

在这里插入图片描述

虚引用

虚引用被回收后会进入引用队列等待,查看代码发现只有一个带队列的构造方法:
在这里插入图片描述
那么我们使用虚引用的目的就是当对象被回收,虚引用会进入引用队列,这是我们从引用队列取出引用后得知对象被回收的信息,进行验尸工作。

public class test {
    public static void main(String[] args) {
        testPhantomReference();
    }


    public static void testPhantomReference() {
        ReferenceQueue rq = new ReferenceQueue();
        byte[] bytes = new byte[1024 * 1024 * 100];

        PhantomReference<byte[]> pr = new PhantomReference<byte[]>(bytes, rq);

        //监控对象是否被清理
        Thread cleanUpThread = new Thread(() -> {
            try {
                while(true){
                    Reference remove = rq.remove();
                    System.out.println("对象被清理了" + remove);
                }
                } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        );
        cleanUpThread.setDaemon(
                true
        );
        cleanUpThread.start();

        bytes = null;
        System.gc();
    }

这里我们启动一个守护线程去监控对象是否被清理,如果被清理则打印清理内容
在这里插入图片描述

JAVA中的引用类型主要包括强引用软引用弱引用引用。 1. 强引用(Strong Reference):最常见的引用类型。只要某个对象有强引用与之关联,垃圾回收器就不会回收该对象。例如:Object obj = new Object(),这时obj是一个强引用,指向了一个对象。 2. 软引用(Soft Reference):对于只有软引用关联的对象,在内存不足时,垃圾回收器可能会回收这些对象。软引用可以通过 SoftReference 类来创建。例如:SoftReference<Object> softRef = new SoftReference<>(obj)。 3. 弱引用(Weak Reference):比软引用更弱一些,只有弱引用关联的对象在垃圾回收时,不论内存是否充足,都会被回收。弱引用可以通过 WeakReference 类来创建。例如:WeakReference<Object> weakRef = new WeakReference<>(obj)。 4. 引用(Phantom Reference):最弱的一种引用关系。引用的对象无法通过引用直接访问,也无法获取对象的任何属性或方法。主要作用是在对象被垃圾回收时,收到一个系统通知。引用可以通过 PhantomReference 类来创建。例如:PhantomReference<Object> phantomRef = new PhantomReference<>(obj, referenceQueue)。 这些引用类型在内存管理中起到不同的作用。强引用是最常用的,其他引用类型通常用于辅助内存管理,例如在缓存、对象池等场景中使用软引用弱引用,或者在处理直接内存时使用引用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值