java中对象的强、软、弱、虚四种引用详解

 更新时间:2023年09月26日 10:33:40   作者:回家放羊吧  
这篇文章主要介绍了java中对象的强、软、弱、虚四种引用详解,对象的引用分为4种,分别是强引用>软引用>弱引用>虚引用,程序员可以通过不同的引用控制对象的生命周期,方便垃圾回收,使程序更加灵活的控制对象生命周期,需要的朋友可以参考下

介绍

java垃圾回收机制通过两种方法来判断对象是否回收,分别是引用计数法可达性分析算法

java在jdk1.2之前,只存在一种引用,当对象只有被引用时才会存在,当没有引用时,引用计数为0,对象就会被垃圾回收判断为失效,进行回收

java在jdk1.2开始,对象的引用分为4种,分别是强引用>软引用>弱引用>虚引用,程序员可以通过不同的引用控制对象的生命周期,方便垃圾回收,使程序更加灵活的控制对象生命周期

java在jdk1.2开始,在java.lang.ref提供了一个抽象类Reference和三个实现类SoftReference(软引用)、WeakReference(弱引用)、PhantomReference(虚引用

强引用

/**
     * 强引用
     */
    public void testStrongReference(){
        //强引用
        Object obj=new Object();
    }

业务代码中的对象,绝大部分都是强引用,比如Object obj=new Object(),这种引用的对象绝对不会被垃圾回收,当内存不足以分配创建对象的内存时,Java虚拟机会抛出OOM错误,使程序异常终止,也不回收这种对象,只有这个引用消失后(* 显式赋值为null*,方法生命周期结束等),引用计数为0,才会被垃圾回收

软引用

/**
     * 软引用
     */
    public void testSoftReference(){
        //强引用
        Object obj=new Object();
        //放入SoftReference
        SoftReference<Object> softReference = new SoftReference<Object>(obj);
        System.out.println( softReference.get());//java.lang.Object@39a054a5
    }

软引用要比强引用低一个等级,用来表示有用非必要的对象,只有当内存不足的时候,才会对软引用对象进行垃圾回收,可以来实现缓存,不用担心存在内存溢出问题。

/**
     * 软引用(引用队列)
     */
    public void testSoftReferenceQueue(){
        //引用队列
        ReferenceQueue referenceQueue = new ReferenceQueue<>();
        //使用守护线程
        Thread thread= new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    int i=0;
                    SoftReference<Integer> softReference;
                    //如果对象被gc回收
                    while((softReference = (SoftReference) referenceQueue.remove()) != null) {
                        System.out.println("第"+i+"次回收:"+softReference);
                        i++;
                    }
                }catch (Exception e){
                }
            }
        });
        thread.setDaemon(true);//设置为守护线程,监听对象变化
        thread.start();
        Map<Object, Object> map = new HashMap<>();
        Object obj=new Object();
        for(int i=0;i<2000; i++){
            //放入SoftReference转为软引用
            byte [] bytes=new byte[1024*1024];
            SoftReference<byte []> softReference = new SoftReference<byte []>(bytes,referenceQueue);
            //将软引用作为key
            map.put(softReference,obj);
        }
    }

第1992次回收:java.lang.ref.SoftReference@7c7a06ec 第1993次回收:java.lang.ref.SoftReference@1d296da 第1994次回收:java.lang.ref.SoftReference@776aec5c [GC (Allocation Failure) [PSYoungGen: 30K->64K(1536K)] 3833K->3866K(5632K), 0.0002270 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 64K->64K(1536K)] 3866K->3866K(5632K), 0.0002042 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) [PSYoungGen: 64K->0K(1536K)] [ParOldGen: 3802K->3802K(4096K)] 3866K->3802K(5632K), [Metaspace: 3120K->3120K(1056768K)], 0.0019695 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 3802K->3802K(5632K), 0.0002220 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 3802K->730K(4096K)] 3802K->730K(5632K), [Metaspace: 3120K->3120K(1056768K)], 0.0025588 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 第1995次回收:java.lang.ref.SoftReference@408d971b 第1996次回收:java.lang.ref.SoftReference@75d4a5c2 第1997次回收:java.lang.ref.SoftReference@557caf28

软引用通过SoftReference来进行实现,可以将软引用对象注册到引用队列(Referencequeue)中,引用队列来判断对象是否被释放,Reference存在next字段,有四种状态,可以根据状态判断,但next仅在放到queue中才会有意义( 因为,只有在enqueue的时候,会将next设置为下一个要处理的Reference对象 )

  • active:内存被分配的时候状态。
  • pending:即将回收内存,存入关联的引用queue中时的状态。
  • Enqueued:内存被回收的时候,进入引用队列中的状态。
  • Inactive:不活跃状态。

弱引用

/**
     * 弱引用
     */
    public void testWeakReference(){
        //强引用
        Object obj=new Object();
        //放入WeakReference
        WeakReference<Object> weakReference = new WeakReference<Object>(obj);
        System.out.println(weakReference.get());//java.lang.Object@39a054a5
    }

弱引用要比软引用第一个等级,用来表示非必要的对象不管内存是否充足,都会垃圾回收其对象,但是因为垃圾回收线程优先级很低,所以不会很快回收 弱引用通过WeakReference来进行实现,可以将弱引用对象注册到引用队列(Referencequeue)中,引用队列来判断对象是否被释放。小伙伴们如果想测试,可以用上面弱引用的线程监听方法

虚引用

/**
     * 虚引用
     */
    public void testPhantomReference(){
        //强引用
        Object obj=new Object();
        //必须使用引用队列
        ReferenceQueue referenceQueue = new ReferenceQueue();
        //放入PhantomReference
        PhantomReference<Object> phantomReference = new PhantomReference<Object>(obj,referenceQueue);
        System.out.println(phantomReference.get());//null 因为虚引用无法获取对象实例,只是监听作用
        System.out.println(obj);//java.lang.Object@39a054a5
    }

虚引用相较于其他引用,就如形同虚设,无法通过虚引用来获取对象实例,如果一个对象仅仅被虚引用持有,则随时会被垃圾回收,和软引用、弱引用不同,其必须注册到Referencequeue中,当对象即将被回收时,就会将虚引用放入到引用队列中,通过判断虚引用是否加入到引用队列来判断对象是否要被回收

到此这篇关于java中对象的强、软、弱、虚四种引用详解的文章就介绍到这了,更多相关java对象四种引用详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java元素排序Comparable与Comparator的区别

    Java元素排序Comparable与Comparator的区别

    这篇文章主要介绍了Java元素排序Comparable与Comparator的区别,二者都是顶级的接口,但拥有的方法和用法是不同的,下面我们分别来看看具体是怎样的区别吧
    2022-05-05
  • Spring Boot优雅地处理404异常问题

    Spring Boot优雅地处理404异常问题

    这篇文章主要介绍了Spring Boot优雅地处理404异常问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • Java lambda 循环累加求和代码

    Java lambda 循环累加求和代码

    这篇文章主要介绍了Java lambda 循环累加求和代码,具有很的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Spring Cloud 的 Hystrix.功能及实践详解

    Spring Cloud 的 Hystrix.功能及实践详解

    这篇文章主要介绍了Spring Cloud 的 Hystrix.功能及实践详解,Hystrix 具备服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并以及服务监控等强大功能,需要的朋友可以参考下
    2019-07-07
  • 详解Java编程中对线程的中断处理

    详解Java编程中对线程的中断处理

    这篇文章主要介绍了Java编程中对线程的中断处理,特别讲解了中断的时机与中断状态的管理,需要的朋友可以参考下
    2015-11-11
  • Java实现简单邮件发送

    Java实现简单邮件发送

    这篇文章主要介绍了Java实现简单邮件发送的相关资料,实例讲解了java邮件发送实现方法,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • 详解Java虚拟机管理的内存运行时数据区域

    详解Java虚拟机管理的内存运行时数据区域

    这篇文章主要介绍了详解Java虚拟机管理的内存运行时数据区域的相关资料,需要的朋友可以参考下
    2017-03-03
  • Redis应用问题及分布式锁使用说明

    Redis应用问题及分布式锁使用说明

    文章主要讨论了缓存穿透、缓存雪崩和分布式锁在高并发场景下的解决方案,包括对空值缓存、设置白名单、布隆过滤器监控、预先设置热门数据、实时调整过期时间、使用锁机制以及构建多级缓存架构等
    2026-03-03
  • SpringBoot中@Pattern注解对时间格式校验方式

    SpringBoot中@Pattern注解对时间格式校验方式

    这篇文章主要介绍了SpringBoot中@Pattern注解对时间格式校验方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • 使用Zxing实现二维码生成器内嵌图片

    使用Zxing实现二维码生成器内嵌图片

    二维码在现实中的应用已经很广泛了,本文介绍了使用Zxing实现二维码生成器内嵌图片,有需要的可以了解一下。
    2016-10-10

最新评论