谈谈Java对象的强引用,软引用,弱引用,虚引用分别是什么

整体结构

java提供了4中引用类型,在垃圾回收的时候,都有自己的各自特点。

为什么要区分这么多引用呢,其实这和Java的GC有密切关系。

强引用(默认支持模式)

  • 把一个对象赋给一个引用变量,这个引用变量就是一个强引用。
  • 强引用是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还活着
  • 当内存不足的时候,jvm开始垃圾回收,对于强引用的对象,就算出现OOM也不会回收该对象的。
    因此,强引用是造成java内存泄露的主要原因之一。
  • 对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显示的将引用赋值为null,GC就会回收这个对象了。

案例

  public static void main(String[] args) {
        Object obj=new Object();//这样定义就是一个强引用
        Object obj2=obj;//也是一个强引用
        obj=null;
        System.gc();
        //不会被垃圾回收
        System.out.println(obj2);
    }

软引用(SoftReference)

  • 软引用是一种相对强化引用弱化了一些引用,需要使用java.lang.SoftReference类来实现。
  • 对于只有软引用的对象来说,
    当系统内存充足时,不会被回收;
    当系统内存不足时,会被回收;

案例

 /**
     * jvm配置配置小的内存,故意产生大的对象,导致OOM,
     * 验证软引用在内存足够的前后是否被回收。
     * 参数:-Xms:5M -Xmx:5M
     * @param args
     */
    public static void main(String[] args) {
        Object obj=new Object();//这样定义就是一个强引用
        //软引用需要使用java.lang.SoftReference来实现
        //现在sf就是一个软引用
        SoftReference sf=new SoftReference(obj);

        obj=null;

        System.out.println("内存足够软引用引用的对象"+sf.get());

        try {
            final byte[] bytes = new byte[8 * 1024 * 1024];
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("内存不够:软引用引用的对象:"+sf.get());
        }

    }

结果:

弱引用

  • 弱引用需要用java.lang.WeakReference类来实现,它比软引用的生存期更短。

* 如果一个对象只是被弱引用引用者,那么只要发生GC,不管内存空间是否足够,都会回收该对象。

  • ThreadLocal静态内部类ThreadLocalMap中的Entiry中的key就是一个虚引用;

案例

 public static void main(String[] args) {
        Object obj=new Object();
        WeakReference wrf=new WeakReference(obj);
        obj=null;
        System.out.println("未发生GC之前"+wrf.get());
        System.gc();
        System.out.println("内存充足,发生GC之后"+wrf.get());
    }

结果:

未发生GC之前[email protected]
内存充足,发生GC之后null

你知道弱引用的话,能谈谈WeakHashMap吗?

WeakHashMap的键是“弱键”,也就是键的引用是一个弱引用。

 public static void main(String[] args) {
        WeakHashMap<String,Integer> map=new WeakHashMap<>();
        String key = new String("wekHashMap");
        map.put(key,1);
        key=null;
        System.gc();
        System.out.println(map);
    }

结果:map为空了。
理论上我们只是把引用变量key变成null了,"wekHashMap"字符串应该被Map中key引用啊,不应该被GC回收啊,
但是因为key是弱引用,GC回收的时候就忽略了这个引用,把对象当成垃圾收回了。

虚引用

  • 虚引用需要 java. langref.PhantomReference类来实现。
  • 顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。
    如果一个对象仅被虛引用持有,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
  • 它不能单独使用也不能通过它访问对象,虚引用必须和引用队列( Reference queue)联合使用。
  • 虚引用的主要作用是跟踪对象被垃圾回收的状态。仅仅是提供了一种确保对象被 finalize以后,做某些事情的机制。
  • PhantomReference的get方法总是返回null,因此无法访问对应的引用对象。
    使用它的意义在于说明一个对象已经进入 finalization阶段,可以被回收,用来实现比 finalization机制更灵活的回收操作
    换句话说,设置虚引用关联的唯一目的,就是在这个对象被收集器回收的时候收到一个系统通知或者后续添加进一步的处理;

ReferenceQueue 引用队列

  • 对象在被回收之前要被引用队列保存一下。GC之前对象不放在队列中,GC之后才对象放入队列中。
  • 【通过开启线程监听该引用队列的变化情况】就可以在对象被回收时采取相应的动作。
    由于虚引用的唯一目的就是能在这个对象被垃圾收集器回收时能收到系统通知,因而创建虚引用时必须要关联一个引用队列,而软引用和弱引用则不是必须的。
    这里所谓的收到系统通知其实还是通过开启线程监听该引用队列的变化情况来实现的。
  • 这里还需要强调的是,
    对于软引用和弱引用,当执行第一次垃圾回收时,就会将软引用或弱引用对象添加到其关联的引用队列中,然后其finalize函数才会被执行(如果没复写则不会被执行);
    而对于虚引用,如果被引用对象没有复写finalize方法,则是在第一垃圾回收将该类销毁之后,才会将虚拟引用对象添加到引用队列,
    如果被引用对象复写了finalize方法,则是当执行完第二次垃圾回收之后,才会将虚引用对象添加到其关联的引用队列
class User{
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("我要被GC干了!");
    }
}
 public static void main(String[] args) throws  Exception {
        User user=new User();
        ReferenceQueue<User> queue=new ReferenceQueue();
        PhantomReference prf=new PhantomReference(user,queue);

        //启动一个线程监控引用队列的变化
        new Thread(()->{
            for(;;){
                final Reference<? extends User> u = queue.poll();
                if (u!=null){
                    System.out.println("有对象被加入到了引用队列了!"+u);
                }
            }
        }).start();

        user=null;
        //GC之前引用队列为空
        System.out.println("GC之前"+queue.poll());

        System.gc();
        Thread.sleep(100);
        //GC之后引用队列才将对象放入
        System.out.println("第一次GC之后"+queue.poll());

        System.gc();
        Thread.sleep(100);
        System.out.println("第二次GC之后"+queue.poll());

    }

结果:

GC之前null
我要被GC干了!
第一次GC之后null
有对象被加入到了引用队列了![email protected]
第二次GC之后[email protected] 

应用场景

软引用:SoftReference的应用场景

假如有一个应用需要读取大量的本地图片
每次读取图片都从硬盘读取会影响性能。
一次全部加载到内存中,又可能造成内存溢出。
此时,可以使用软引用解决问题;
使用一个HashMap保存图片的路径和响应图片对象关联的软引用之间的映射关系,
内存不足时,jvm会自动回收这些缓存图片对象所占用的空间,可以避免OOM。

Map<String,SoftReference<Bigmap>> imageCache=new HashMap<String,SoftReference<Bitmap>>();

原文地址:https://www.cnblogs.com/wangsen/p/11206956.html

时间: 2024-08-27 21:51:58

谈谈Java对象的强引用,软引用,弱引用,虚引用分别是什么的相关文章

Java:对象的强、软、弱和虚引用(转)

1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级别由高到低依次为:强引用.软引用.弱引用和虚引用.图1为对象应用类层次. 图1 ⑴强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空

Java对象的强、软、弱和虚引用原理+结合ReferenceQueue对象构造Java对象的高速缓存器

//转 http://blog.csdn.net/lyfi01/article/details/6415726 1.Java对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.这 就像在日常生活中,从商店购买了某样物品后,如果有用,就一直保留它,否则就把它扔到垃圾箱,由清洁工人收走.一般说来,如果物品已经被扔到垃圾箱,想再 把它捡回来使用就不可能了. 但有时候情况

Java:对象的强、软、弱和虚引用

本文介绍对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. author: ZJ 07-12-1 Blog: [url]http://zhangjunhd.blog.51cto.com/[/url] 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级

java中四种引用类型(对象的强、软、弱和虚引用)

对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级别由高到低依次为:强引用.软引用.弱引用和虚引用. ⑴强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足,Java虚拟机宁愿抛出O

java基础知识再学习--集合框架-对象的强、软、弱和虚引用

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://zhangjunhd.blog.51cto.com/113473/53092 本文介绍对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. author: ZJ 07-12-1 Blog: [url]http://zhangjunhd.blog.51cto.com/[/url] 1.对象的强.软.弱和虚引用 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序

【转】对象的强、软、弱和虚引用

对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级别由高到低依次为:强引用.软引用.弱引用和虚引用. ⑴强引用(StrongReference)强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足,Java虚拟机宁愿抛出Out

强、软、弱和虚引用的概念

本文介绍对象的强.软.弱和虚引用的概念.应用及其在UML中的表示. 1.对象的强.软.弱和虚引用   在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级别由高到低依次为:强引用.软引用.弱引用和虚引用.图1为对象应用类层次. 图1 ⑴强引用(StrongReference)    强引用

Java中强、软、弱、虚引用

一.前言 忘记之前是怎么接触到Java的强.软.弱.虚引用的了,恍恍惚惚好像是在看垃圾回收的时候,略过了这些个概念~这些知识在平时开发中使用的真是少之又少(也许我的level还不够)~今天就将这些整理完毕吧~ 二.正文 对于Java中这几种引用的理解,有助于理解JVM的回收内存的机制.先说下在JVM执行垃圾回收时,如何处理它们所引用的对象: 1)强引用,任何时候都不会被垃圾回收器回收,如果内存不足,宁愿抛出OutOfMemoryError. 2)软引用,只有在内存将满的时候才会被垃圾回收器回收,

详解Java中对象的软、弱和虚引用的区别

对于大部分的对象而言,程序里会有一个引用变量来引用该对象,这是最常见的引用方法.除此之外,java.lang.ref包下还提供了3个类:SoftReference.WeakReference和PhantomReference.它们分别代表了系统对对象的另外3中引用方式:软引用.弱引用和虚引用. Java中四种引用的区别和关联: 强引用.这是Java中最常见的引用方式.程序创建一个对象,并把这个对象赋给一个引用变量,程序通过该引用变量来操作实际的对象.当一个对象被一个或者多个引用变量引用时,它处于

4中引用(强,软,弱,虚)侧重弱引用

1,强引用,对象有强引用与之关联,即使在内存不足,抛出OutOfMemory错误也不会回收这种对象 2,软引用是用来描述一些有用但并不是必需的对象,java.lang.ref.SoftReference类来表示. 对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象.可以很好地用来解决OOM的问题,适合用来实现缓存:比如网页缓存.图片缓存等. 软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列