Java的强引用、弱引用、软引用和虚引用

Java种除了基本数据类型,其它数据类型都是引用的数据类型。而应用数据类型根据生命周期的长短又分为:强引用、弱引用、软引用和需引用(幻象引用),我们平时基本上只用到强引用类型,而其他的引用类型我们也就在面试中,或者平日阅读类库或其他框架源码的时候才能见到。

1.强引用

用到的new了一个对象就是强引用,例如 Object obj = new Object();

当JVM的内存空间不足时,宁愿抛出OutOfMemoryError使得程序异常终止也不会回收具有强引用的存活着的对象!

强引用对象回收:

当一个普通对象没有其他引用关系,只要超过了引用的作用域或者显示的将引用赋值为null时,你的对象就表明不是存活着,这样就会可以被GC回收了。当然回收的时间是不一定的具体得看GC回收策略。

2.软引用

软引用的生命周期比强引用短一些。软引用是通过SoftReference类实现的。

Object obj = new Object();
//SoftReference softObj = new SoftReference(obj);//转换为软引用

ReferenceQueue qu = new ReferenceQueue()
SoftReference softObj = new SoftReference(obj, qu);
obj = null; //去除强引用

  这样就是一个简单的软引用使用方法。当JVM认为内存空间不足时,就回去试图回收软引用指向的对象,也就是说在JVM抛出OutOfMemoryError之前,会去清理软引用对象。软引用可以与引用队列(ReferenceQueue)联合使当softObj软引用的obj被GC回收之后,softObj 对象就会被塞到queue中,之后我们可以通过这个队列的poll()来检查你关心的对象是否被回收了,如果队列为空,就返回一个null。反之就返回软引用对象也就是softObj。软引用一般用来实现内存敏感的缓存,如果有空闲内存就可以保留缓存,当内存不足时就清理掉,这样就保证使用缓存的同时不会耗尽内存。例如图片缓存框架中缓存图片就是通过软引用的。

用途:比如考虑一个图像编辑器的程序。该程序会把图像文件的全部内容都读取到内存中,以方便进行处理。而用户也可以同时打开多个文件。当同时打开的文件过多的时候,就可能造成内存不足。如果使用软引用来指向图像文件内容的话,垃圾回收器就可以在必要的时候回收掉这些内存。

3.弱引用

Object obj = new Object();
WeakReference<Object>  weakObj = new WeakReference<Object>(obj);
obj = null;

  

弱引用是通过WeakReference类实现的,它的生命周期比软引用还要短,也是通过get()方法获取对象。在GC的时候,不管内存空间足不足都会回收这个对象,同样也可以配合ReferenceQueue 使用,也同样适用于内存敏感的缓存。ThreadLocal中的key就用到了弱引用。

用途:

弱引用的作用在于解决强引用所带来的对象之间在存活时间上的耦合关系。弱引用最常见的用处是在集合类中,尤其在哈希表中。哈希表的接口允许使用任何Java对象作为键来使用。当一个键值对被放入到哈希表中之后,哈希表对象本身就有了对这些键和值对象的引用。如果这种引用是强引用的话,那么只要哈希表对象本身还存活,其中所包含的键和值对象是不会被回收的。如果某个存活时间很长的哈希表中包含的键值对很多,最终就有可能消耗掉JVM中全部的内存。

  对于这种情况的解决办法就是使用弱引用来引用这些对象,这样哈希表中的键和值对象都能被垃圾回收。Java中提供了WeakHashMap来满足这一常见需求。

4.幻象引用

也称虚引用,是通过PhantomReference类实现的。任何时候可能被GC回收,就像没有引用一样。无法通过虚引用访问对象的任何属性或者函数。那就要问了要它有什么用?虚引用仅仅只是提供了一种确保对象被finalize以后来做某些事情的机制。比如说这个对象被回收之后发一个系统通知啊啥的。虚引用是必须配合ReferenceQueue 使用的,具体使用方法和上面提到软引用的一样。主要用来跟踪对象被垃圾回收的活动。

幽灵引用及其队列的使用情况并不多见,主要用来实现比较精细的内存使用控制,这对于移动设备来说是很有意义的。程序可以在确定一个对象要被回收之后,再申请内存创建新的对象。通过这种方式可以使得程序所消耗的内存维持在一个相对较低的数量。比如下面的代码给出了一个缓冲区的实现示例。

public class PhantomBuffer {

  private byte[] data = new byte[0];
    private ReferenceQueue<byte[]> queue = new ReferenceQueue<byte[]>();
    private PhantomReference<byte[]> ref = new PhantomReference<byte[]>(data, queue);
    public byte[] get(int size) {
        if (size <= 0) {
            throw new IllegalArgumentException("Wrong buffer size");
        }
        if (data.length < size) {
            data = null;
            System.gc(); //强制运行垃圾回收器
             try {
                queue.remove(); //该方法会阻塞直到队列非空
                ref.clear(); //幽灵引用不会自动清空,要手动运行
                ref = null;
                data = new byte[size];
                ref = new PhantomReference<byte[]>(data, queue);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
       }
       return data;
    }
}

  在上面的代码中,每次申请新的缓冲区的时候,都首先确保之前的缓冲区的字节数组已经被成功回收。引用队列的remove方法会阻塞直到新的幽灵引用被加入到队列中。不过需要注意的是,这种做法会导致垃圾回收器被运行的次数过多,可能会造成程序的吞吐量过低。

 

部分引用:https://baijiahao.baidu.com/s?id=1629253892215446066&wfr=spider&for=pc

原文地址:https://www.cnblogs.com/mlfz/p/11684185.html

时间: 2024-11-11 11:03:16

Java的强引用、弱引用、软引用和虚引用的相关文章

java 谈谈引用(强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference))

简单谈谈引用(摘自java虚拟机第二版 ) 署名:wander   一.四种引用 在JDK 1.2之后,Java对引用的概念进行了扩充,将引用分为强引用(Strong Reference).软引用(Soft Reference).弱引用(Weak Reference).虚引用(Phantom Reference)4种,这4种引用强度依次逐渐减弱. 二.引用介绍及回收时机 1.强引用 >>> 就是指在程序代码之中普遍存在的,类似"Object obj=new Object()&q

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

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

java对象的强引用,软引用,弱引用和虚引用

从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期.这四种级别由高到低依次为:强引用.软引用.弱引用和虚引用. 1.强引用 以前我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用.如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它.当内存空 间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题.一般都是new出来的. Object o=new

Java 强引用、 软引用、 弱引用、虚引用

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

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

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

[转]Java 的强引用、弱引用、软引用、虚引用

1.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.如下: Object o=new Object(); // 强引用 当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题.如果不使用时,要通过如下方式来弱化引用,如下: o=null; // 帮助垃圾收集器回收此对象 显式地设置o为null,或超出对象的生命周期范围,则gc认为该对象不

Java中强、软、弱、虚引用

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

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四种引用(强引用,弱引用,软引用,虚引用)

转自:http://www.cnblogs.com/gudi/p/6403953.html 1.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.如下: Object o=new Object(); // 强引用 当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题.如果不使用时,要通过如下方式来弱化引用,如下: o=null; // 帮

java强引用,软引用,弱引用,虚引用

用了Java怎么长时间一直不知道原来Java还有四种引用类型,这个引用类型和我们平常说的可不一样.这里的引用类型不是指数据类型的一种,而是指Java中的引用所分的四种类型.他们代表了JVM回收内存的四种强度,分别如下. 强引用: Java中的引用,有点像C++的指针.通过引用,可以对堆中的对象进行操作.在某函数中,当创建了一个对象,该对象被分配在堆中,通过这个对象的引用才能对这个对象进行操作. Object o=new Object(); 假设以上代码是在函数体内运行的,那么局部变量o将被分配在