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对象四种引用详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot默认扫描的路径方式

    springboot默认扫描的路径方式

    这篇文章主要介绍了springboot默认扫描的路径方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 解决找不到符号 符号:变量 log问题

    解决找不到符号 符号:变量 log问题

    这篇文章主要介绍了解决找不到符号 符号: 变量 log问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 如何基于java语言实现八皇后问题

    如何基于java语言实现八皇后问题

    这篇文章主要介绍了如何基于java语言实现八皇后问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • java 接口回调实例详解

    java 接口回调实例详解

    这篇文章主要介绍了java 接口回调实例详解的相关资料,所谓回调就是使用java中的多态,需要的朋友可以参考下
    2017-07-07
  • java基本教程之Thread中start()和run()的区别 java多线程教程

    java基本教程之Thread中start()和run()的区别 java多线程教程

    这篇文章主要介绍了Thread中start()和run()的区别,Thread类包含start()和run()方法,它们的区别是什么?下面将对此作出解答
    2014-01-01
  • Java单例的写法详解

    Java单例的写法详解

    在java中,单例有很多种写法,面试时,手写代码环节,除了写算法题,有时候也会让手写单例模式,这里记录一下单例的几种写法和优缺点。需要的朋友可以参考下
    2021-09-09
  • Java通过apache poi生成excel实例代码

    Java通过apache poi生成excel实例代码

    本篇文章主要介绍了Java通过apache poi生成excel实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Windows系统编写bat脚本启动、停止及重启Java服务jar包

    Windows系统编写bat脚本启动、停止及重启Java服务jar包

    在bat文件中我们将编写一些代码来运行Java jar文件,下面这篇文章主要给大家介绍了关于Windows系统编写bat脚本启动、停止及重启Java服务jar包的相关资料,需要的朋友可以参考下
    2023-12-12
  • Java如何配置IDEA自定义注释

    Java如何配置IDEA自定义注释

    在IDEA中设置自动创建类和方法的注释可以提高编码效率,确保代码的一致性和可读性,首先,对于创建类的注释,可以通过修改File→Settings→File and Code Templates→Class的模板来实现,其次,对于方法注释
    2024-10-10
  • springBoot mybatis 包扫描实例

    springBoot mybatis 包扫描实例

    这篇文章主要介绍了springBoot mybatis 包扫描实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07

最新评论