JVM学习(五)对象的引用类型

一、引言

  前面我们学习了JVM的垃圾回收机制,我们知道了垃圾回收是JVM的自发行为;虽然我们可以通过System.gc() Runtime.getRuntime().gc()进行显式调用垃圾回收 ,但JVM可以屏蔽掉显式的垃圾回收调用,且JVM也有自己的一套垃圾回收机制,那么我们有没有什么办法可以“告诉”JVM,哪些对象是可以使用以后回收,哪些对象保留呢?这里就要说一下JAVA对象的引用类型了。

二、对象引用的简单介绍

  • 强引用:无论内存是否足够,不会回收。
  • 软引用:内存不足时,回收该引用关联的对象。
  • 弱引用:垃圾回收时,无论内存是否足够,都会回收。
  • 虚引用:任何时候都可能被垃圾回收器回收。

Java中提供这四种引用类型主要有两个目的:

    • 1、让程序员通过代码的方式决定某些对象的生命周期
    • 2、第二是有利于JVM进行垃圾回收。

三、对象引用代码示例

强引用

  强引用是我们使用的最广泛,也是最普遍的一种引用类型,常见的创建对象的方式就使用的强引用:

//1、强引用示例
String str = new String();

特点:

  • 只要某个对象是强引用的,或者有强引用与之关联,JVM必定不会回收这个对象
  • 内存不足的情况下,JVM会抛出OutOfMemory错误
  • 需要回收时,可以显式设置此对象为null,JVM就会自行在垃圾回收发生时去回收此对象

软引用

  软引用是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.SoftReference类来表示。对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象:

//2、软引用示例
SoftReference<String> softStr = new SoftReference<String>(new String("这是一个软引用类型的字符串对象"));
System.out.println(softStr.get());

  软引用相对与强引用来说,比较好的解决了OOM【Out Of Memory】的问题,可以把一些有用的数据,但又不是核心的内容通过软引用的形式来设置,那么当内存不足时就可以回收释放空间了。常见应用如软引用一个图片对象等。

特点:

  • SoftReference类包裹引用
  • JVM内存不足时会回收【存在强引用关联时不回收】

弱引用

  弱引用也是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.WeakReference类来表示。对于弱引用关联着的对象,当JVM进行垃圾回收时,无论内存是否充足,都会回收:

//3、弱引用示例
WeakReference<String> weekStr = new WeakReference<String>(new String("这是一个弱引用类型的字符串对象"));
System.out.println(weekStr.get());
//显式调用JVM垃圾回收
System.gc();
//输出弱引用的内容【此时会输出null,因为在显式调用垃圾回收的时候,弱引用对象的内容已经被回收了】
System.out.println(weekStr.get());

  PS:如果弱引用对象有对应的强引用关联,那么垃圾回收时是不会回收此弱引用的【软引用也类似】

特点:

  • WeakReference类包裹引用
  • JVM无论内存充足与否会在垃圾回收时回收【存在强引用关联时不回收】

虚引用

  虚引用不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收

//4、虚引用示例
//4.1、创建一个引用队列【虚引用必须跟引用队列关联使用】
ReferenceQueue<String> queue = new ReferenceQueue<String>();
//4.2、创建一个虚引用包裹一个字符串对象的引用地址
PhantomReference<String> phantomStr = new PhantomReference<String>(new String("这是一个虚引用类型的字符串对象"), queue);
//4.3、输出引用内容【结果发现输出为null】
System.out.println(phantomStr.get());

特点:

  • PhantomReference类包裹引用
  • 任何时候都可能被垃圾回收器回收
  • 必须跟引用队列关联使用

引用队列(ReferenceQueue)

作用:

  • 用于监听Reference所指向的对象是否已经被垃圾回收

使用场景:

  • 当大量使用各种引用(Reference)来包裹实例对象时,虽然引用(Reference)指向的对象可能被回收了,但Reference本身也是个对象,所以也需要回收,这时就需要使用ReferenceQueue了。

回收模式上的区别:

  • SoftReferenceWeakReference的get()加入ReferenceQueue或get()返回null时,仅是表明其指示的对象已经进入垃圾回收流程,此时对象不一定已经被垃圾回收。
  • PhantomReference加入ReferenceQueue时,则表明对象需要且已被回收PS:所以虚引用的例子的4.3步骤,调用get方法时返回会为null】

 

 

posted @ 2020-04-21 09:41  有梦想的肥宅  阅读(279)  评论(0编辑  收藏  举报