java强应用,软引用,弱引用,虚引用的区别

本文详细介绍了Java中的强引用、软引用、弱引用和虚引用,阐述了它们的区别和应用场景,并通过代码实验验证了不同引用类型的生命周期和垃圾回收行为。在内存管理中,软引用和弱引用常用于缓存,而虚引用则用于跟踪对象被回收的时机。实验结果显示,弱引用和虚引用的对象在GC后会被立即回收,而软引用则在内存不足时才会被回收。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

各个引用的区别

强引用: 强引用指的是通过new对象创建的引用,垃圾回收器即使是内存不足也不会回收强引用指向的对象。

软引用: 软引用是通过SoftRefrence实现的,它的生命周期比强引用短,在内存不足,抛出OOM之前,垃圾回收器会回收软引用引用的对象。软引用常见的使用场景是存储一些内存敏感的缓存,只有当内存不足时会被回收。

弱引用: 弱引用是通过WeakRefrence实现的,它的生命周期比软引用还短,GC只要扫描到弱引用的对象就会回收。弱引用常见的使用场景也是存储一些内存敏感的缓存。

虚引用: 虚引用是通过PhantomRefrence实现的,它的生命周期最短,随时可能被回收。如果一个对象只被虚引用引用,我们无法通过虚引用来访问这个对象的任何属性和方法。get()返回的都是null,它的作用仅仅是保证对象在finalize后,做某些事情。虚引用常见的使用场景是跟踪对象被垃圾回收的活动,当一个虚引用关联的对象被垃圾回收器回收之前会收到一条系统通知。

实验来验证:

package com.figo.test;

import lombok.Getter;
import lombok.Setter;
import org.junit.jupiter.api.Test;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;

/**
 * @ClassName:ReferenceTest
 * @PackageName:com.figo.test
 * @Description:类描述
 * @Date:2022/7/20 10:49
 * @Author:figo
 */
public class ReferenceTest {
    private ReferenceQueue<? super Employee> referenceQueue;

    public class Employee
    {
        @Getter
        @Setter
        String name="andy";

        @Getter
        @Setter
        int age=100;
    }
    @Test
    public void testReference(){
        //new出来是强引用
        Employee employee = new Employee();//调用无参构造函数,自动为相关属性赋值
        //软引用,在内存没有出现oom时不会被回收,不能和WeakReference一起使用,否则WeakReference失效
        //SoftReference<Employee> employeeSoftReference = new SoftReference<>(employee);
        //弱引用
        WeakReference<Employee> employeeWeakReference=new WeakReference<>(employee);
        //虚引用
        referenceQueue=new ReferenceQueue<>();
        PhantomReference<Employee> employeePhantomReference=new PhantomReference<>(employee, referenceQueue);

        System.out.println("------Before Gc------");
        //System.out.println("软引用对象是否还在="+employeeSoftReference.get());
        System.out.println("弱引用对象是否还在="+employeeWeakReference.get());
        System.out.println("虚引用对象是否还在="+employeePhantomReference.get());

        employee=null;//被引用对象清空
        System.gc();//进行垃圾回收, 底部实现Runtime.getRuntime().gc();

        System.out.println("------After Gc------");
        //System.out.println("软引用对象是否还在="+employeeSoftReference.get());
        System.out.println("弱引用对象是否还在="+employeeWeakReference.get());
        System.out.println("虚引用对象是否还在="+employeePhantomReference.get());

        //向堆中填充数据模拟OOM
        List<Byte[]> list = new LinkedList<>();
        try{
            for (int i = 0; i < 10000; i++) {
                //System.out.println("SoftReference == "+employeeSoftReference.get());
                list.add(new Byte[1*1024*1024]);
            }
        }catch (Throwable e){
            System.out.println("------After OOM------");
            //System.out.println("软引用对象是否还在="+employeeSoftReference.get());
            System.out.println("弱引用对象是否还在="+employeeWeakReference.get());
            System.out.println("虚引用对象是否还在="+employeePhantomReference.get());
            e.printStackTrace();
        }
    }
}

输出结果:

------Before Gc------
弱引用对象是否还在=com.chinapay.pointconsumer.test.ReferenceTest$Employee@57f23557
虚引用对象是否还在=null
------After Gc------
弱引用对象是否还在=null
虚引用对象是否还在=null
------After OOM------
弱引用对象是否还在=null
虚引用对象是否还在=null
java.lang.OutOfMemoryError: Java heap space
    at com.chinapay.pointconsumer.test.ReferenceTest.testReference(ReferenceTest.java:63)
    

另外提示一下软引用和弱引用不能同时使用,否则gc后发现弱引用引用的对象还是存在的,因为软引用只有在oom后对象才会被当做垃圾回收。

将上面的代码改成注释弱引用后,实验结果:

------Before Gc------
软引用对象是否还在=com.chinapay.pointconsumer.test.ReferenceTest$Employee@57f23557
虚引用对象是否还在=null
------After Gc------
软引用对象是否还在=com.chinapay.pointconsumer.test.ReferenceTest$Employee@57f23557
虚引用对象是否还在=null
------After OOM------
软引用对象是否还在=null
虚引用对象是否还在=null
java.lang.OutOfMemoryError: Java heap space

开发中,对于一些缓存的使用,如果对业务影响不大,在出现内存不足时希望优先被回收的,可以使用SoftReference或者WeakReference。

参考文档:Java:Java的四种引用与其中区别_VoldemortQian的博客-优快云博客_java四种引用的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值