栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【面试】JAVA四种引用 -强引用、软引用、弱引用、虚引用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【面试】JAVA四种引用 -强引用、软引用、弱引用、虚引用

目录

概述

强引用

软引用

典型使用场景

弱引用

典型使用场景

虚引用

 典型使用场景

场景验证

Cleaner

示例代码

输出结果


概述

        Java中的引用关系可以分为强引用,软引用(SoftReference)、弱引用(WeakReference)和虚引用(PhantomReference);引用与对象以及GC Root直接的关系如下图所示:

强引用

     强引用就是普通的赋值语句,只要GC Root到对象之间存在引用关系,改对象就不会被回收

软引用

        软引用要弱于强引用,在GC Root 到引用对象之间还存在可达关系,只要JVM认为存在OOM风险就可以被回收

典型使用场景

        1.缓存,被回收不影响系统可用性;比如在JDK反射中使用较多

弱引用

        弱引用关系要比软引用之间的关系更弱,只要发生GC就会被回收,不管内存空间是否充足;也可以配合引用队列使用

典型使用场景

        1.缓存,比如WeakHashMap, ThreadLocal等

虚引用

        虚引用是最特殊的一个引用,虚引用的简单来讲就是形同虚设,无法从引用中获取引用对象,既然这样,虚引用的作用是什么呢?它主要用来跟踪对象被垃圾回收的活动,当垃圾
回收器准备回收这个对象时,如果发现它有虚引用就会将这个虚引用添加到与之关联的引用队列中。

 典型使用场景

      对象回收时,清理关联资源,比如Cleaner,以及堆外缓存管理等。

场景验证

为了验证是引用关系是否如上文所述,特准备如下代码:

public class 四种引用 {



    public static void main(String[] args) throws InterruptedException {


        //强引用
        Object strongReference = new Object();

        //引用队列
        ReferenceQueue referenceQueue = new ReferenceQueue<>();
        
        SoftReference softReference = new SoftReference<>(new Object(), referenceQueue);

        //reference handler
        new Thread(() -> {
            try {
                Reference reference = null;
                while ((reference = referenceQueue.remove()) != null) {
                    if (reference instanceof SoftReference) {
                        System.out.println("软引用引用对象被回收");
                    }
                    if (reference instanceof PhantomReference) {
                        System.out.println("虚引用引用对象被回收");
                    }
                    if (reference instanceof WeakReference) {
                        System.out.println("弱引用引用对象被回收");
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();
        
        WeakReference weakReference = new WeakReference<>(new Object(), referenceQueue);

        System.out.println("弱引用:" + weakReference.get());
        //手动执行GC,
        System.gc();
        // 手动执行GC 后 弱引用被引用的对象已经被回收了,此时get到的值为null
        System.out.println("弱引用:" + weakReference.get());

        
        PhantomReference phantomReference = new PhantomReference<>(new Object(), referenceQueue);


        try {
            SoftReference holder = new SoftReference<>(new HashMap<>());
            for (int i = 0; i < 1000; i++) {
                HashMap hashMap = holder.get();
                Thread.sleep(20);
                if (Objects.nonNull(hashMap)) {
                    hashMap.put(i, new Object[1024]);
                }
                if (softReference.get() == null) {
                    System.out.println("强引用: " + strongReference);
                    System.out.println("软引用:" + softReference.get());
                    break;
                }
            }
        } catch (Throwable e) {
            System.out.println("OutOfMemoryError后:" + softReference.get());
        }
        System.out.println("强引用: " + strongReference);
        System.out.println("软引用:" + softReference.get());
        System.out.println("弱引用:" + weakReference.get());
        System.out.println("虚引用 " + phantomReference.get());

        TimeUnit.SECONDS.sleep(20);
        System.exit(-1);
    }
    
}
 

jvm 参数:-Xms3m -Xmx3m 执行结果如下:

弱引用:java.lang.Object@5ca881b5
[0.087s][info   ][gc,start    ] GC(1) Pause Full (System.gc())
弱引用引用对象被回收
弱引用:null
[1.193s][info   ][gc,ergo        ] Attempting maximum full compaction clearing soft references
软引用引用对象被回收
虚引用引用对象被回收
强引用: java.lang.Object@24d46ca6
软引用:null
强引用: java.lang.Object@24d46ca6
软引用:null
弱引用:null
虚引用 null

Cleaner

         在程序执行过程中创建的对象将由垃圾收集器 (GC)自动删除。当某个对象未被任何线程引用时,并且当JVM确定无法访问该对象时,则可以进行垃圾回收。
 Object类具有finalize() 方法,在尝试从堆中删除对象之前,GC 将自动调用该方法。在Java 9中,已经不建议使用finalize()方法,并将新类java.lang.ref.Cleaner 添加到垃圾回收管理中。当对象可以进行垃圾回收时,Cleaner 类的对象会自动得到通知。需要通过使用register()方法向清理器对象注册正在垃圾回收的对象

示例代码
public class CleanerTest {
    public static void test() {
        Object instance = new Object();
        Cleaner cleaner = Cleaner.create();
        cleaner.register(instance, () -> {
            System.out.println("do cleaner");
        });
    }

    public static void main(String[] args) {
        System.out.println("Cleaner Test");
        test();
        System.gc();
    }
}

输出结果

Cleaner Test
do cleaner

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号