JVM的四种引用

JVM四种引用

如果一个对象存在引用,那么该引用对象不会被回收? – 局限性
只适用于强引用对象。

强引用

Object obj = new Object(); // 一般使用new

约定: 引用obj , 引用对象new Object()

强引用对象(new Object())什么时候失效?

1. 生命周期结束(作用域失效)

public void method() {
    Object obj = new Object();
} // 方法执行完毕,强引用对象指向的引用对象就会等待被gc回收

2. 引用置为null

obj = null; // 引用对象等待被gc回收

除了以上两种情况,其他任何时候(即使JVM内存溢出)gc都不会回收强引用对象。

软引用

软引用: 内存不足时会回收

解决强引用的强势问题 ===> 除了两种情况,任何时候(即使JVM内存溢出)gc都不会回收强引用对象
内存不足了,即使还在使用,也可能会被回收。

可作为缓存淘汰策略(内存不足,gc自动回收)

java.lang.ref.SoftReference

装饰者模式

// 构造器层层套娃
// 装饰者模式: 强引用对象包裹一下成为软引用对象
SoftReference<SoftObject> softReference = new SoftReference<>(new SoftObject());
// io中的装饰者模式: 字符串 -> 文件 -> 文件流 -> 转换流(字符流) -> 缓冲字符流  
//new BufferedReader(new InputStreamReader(new FileInputStream(new File("c:\\program\\xxx"))));

验证

public static void main(String[] args) throws FileNotFoundException {
    // 装饰者模式:构造器层层套娃, 强引用对象包裹一下成为软引用对象
    // new BufferedReader(new InputStreamReader(new FileInputStream(new File("c:\\program\\xxx"))));
    SoftReference<SoftObject> softReference = new SoftReference<>(new SoftObject());
    // SoftObject obj = softReference.get();// 返回new SoftObject()对象

    ArrayList<byte[]> list = new ArrayList<>();

    // 验证
    new Thread(() -> {
        while (true) {
            // **********这里必须加上一段内容,防止while死循环导致该工作内存无法同步softReference.get()值
            // **********也不要使用obj值替换softReference.get()
            System.out.println("-----");
            if (softReference.get() == null) { // 如果对象被回收,退出jvm
                System.out.println("软引用对象被回收");
                System.exit(0);
            }
        }
    }).start();

    while (true) { // -Xmx=128m -Xms=64m
        if (softReference.get() != null) {
            list.add(new byte[1024*1024]);
        }
    }
}

弱引用

只要gc执行,弱引用就会被回收(不管内存足不足)

public static void main(String[] args) {
    WeakReference<Object> weakReference = new WeakReference<>(new Object());
    System.out.println(weakReference.get() == null ? "已被回收": "未被回收");
    System.gc(); // 建议gc执行一次回收(存在概率)
    System.out.println(weakReference.get() == null ? "已被回收": "未被回收");
}

虚引用

幻影引用或者幽灵引用

java.lang.ref.PHantomReference<T>
是否使用虚引用,和引用对象本身没有任何关系;
无法通过虚引用来获取对象本身
虚引用get() = null
虚引用不会单独使用,一般会和引用队列ReferenceQueue一起使用
价值:当gc回收一个对象,如果gc发现此对象还有一个虚引用,就会将虚引用放入引用队列中,之后(当虚引用出队后)再去回收该对象。
因此,我们可以使用虚引用+引用队列实现在对象被gc回收之前,进行一些额外的操作
GC -> 如果有虚引用 -> 虚引用入队 -> 虚引用出队 -> 回收对象
特殊情况:如果虚引用对象重写了finalize方法,那么引用对象入队时机就会被延迟,可能是延迟到下一次执行gc

验证

 public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        // 引用队列
        ReferenceQueue queue = new ReferenceQueue();
        // 虚引用 + 引用队列
        PhantomReference<Object> phantomReference = new PhantomReference<>(obj, queue);
        // gc执行
        obj = null;
        System.gc();
        Thread.sleep(30);
        System.out.println("gc执行");
        // 执行入队...

        // GC -> 如果有虚引用 -> 虚引用入队 -> 虚引用出队 -> 回收对象
        System.out.println(queue.poll());
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值