辨析Java的四种引用,那我走?

323 阅读2分钟

这是我参与更文挑战的第7天,活动详情查看: 更文挑战

来到更文的第七天,也是6.7高考的日子,正在参加高考的学弟学妹们,希望你们考啥啥会,金榜题名!

没有对象怎么面向对象编程呢?真让人头秃!

读这篇文章之前可以先看一下上面这个链接的第四小节,可以帮助我们理解这四种引用!

这篇文章介绍一下Java的四种引用,给介绍ThreadLocal做准备! Java内存管理分为内存分配,和内存回收,内存回收是由垃圾回收器自己负责的,有专门的垃圾回收机制,而垃圾回收机制主要看对象是否有引用指向这个对象,而引用的强弱,就是这四种引用:强引用,软引用,弱引用,和虚引用!

1、强引用

强引用是指创建一个对象并赋给它一个引用,这个就是强引用

   praivate static void strongReference(String[] args){
       Object o=new Object();
       //TO Do 做很多事情
       //TO DO 做很多事情
       
   }
    

因为o 是局部变量在strongReference方法执行完的时候,o会被JVM自动回收,但是因为它是一个强引用,当strongReference还没执行完的时候内存不够用了,JVM是不会回收 o的,会抛出out of Memory异常!,如果想中断引用,直接把o置为null即可,然后gc回收的时候就会o的实例回收掉

2、软引用

如果一个对象具有软引用,只要内存足够,它就不会被GC回收,只有即将快要发生oom的时候,gc会回收具有软引用的对象 GC:快要发生OOM了!

具有软引用的对象:

2b663a1b6660abd81ff17c5601c5570a.jpeg

GC:走你!

GC就把具有软引用的对象给带走了! 软引用可以用于内存敏感的缓存,比如图片缓存,内存不足的时候图片加载不出来,但是不会oom,这样我们的代码就会好很多

public class TestDemo {

    static class User{

    }
    public static void main(String[] args) {
        User user=new User();//这是一个强引用
        SoftReference<User> userSoftReference=new SoftReference<>(user);//软引用
        user=null;
        System.out.println(userSoftReference.get());//确定这个对象是否还在
        System.gc();//进行一次垃圾回收,这个代码千万不要写到业务代码中
        System.out.println(userSoftReference.get());
        List<byte[]> list=new LinkedList<>();
        try {
            for (;;){
                list.add(new byte[1024*100]);
            }
        }catch (Throwable throwable){
            throwable.printStackTrace();
            //这个时候持有软引用的User已经走你了
            System.out.println(userSoftReference.get());

        }

    }
}

运行结果

image.png

3、弱引用

弱引用比软引用还要弱一点,只存活在下一次gc之前,用于不是那么重要的数据的引用

    public static void main(String[] args)  {
        User user=new User();//这是一个强引用
        WeakReference<User> userWeakReference=new WeakReference<>(user);//弱引用
        user=null;
        System.out.println(userWeakReference.get());//确定这个对象是否还在
        System.gc();//进行一次垃圾回收,这个代码千万不要写到业务代码中
        System.out.println(userWeakReference.get());
       
    }

运行结果:

image.png

弱引用的使用场景和软引用差不多,只是弱引用它的生命周期更短一些, 弱引用的使用场景,Handler内存泄漏,ThreadLocal里的ThreadLocalMap的Entry

image.png

使用它们就是为了避免内存泄漏

4、虚引用PhantomReference

虚引用也叫幽灵引用,随时可能被回收掉,它在使用的时候必须集合ReferenceQueue

  public static void main(String[] args) throws FileNotFoundException {
        ReferenceQueue<String> referenceQueue=new ReferenceQueue<>();
        PhantomReference<String> phantomReference=new PhantomReference<>(new String("aa"),referenceQueue);
        System.out.println(phantomReference.get());
        
        }

运行结果:

image.png

这个虚引用在我们平时开发中,很少用到。它的作用就是来监听垃圾回收器是否在正常工作!

5、总结

四个引用,其实代表了垃圾回收时的优先级,强引用如果不中断引用的话不会被回收的,即使你发生了oom,而软引用就是内存不够的时候,垃圾回收器才会回收它,而弱引用只要发生垃圾回收,它就会被回收,虚引用只要出来它就会被回收,说明gc是在正常工作,如果没有被回收,可能垃圾回收器出现了问题!