【J2SE】这才是java虚引用(PhantomReference)

一、java.lang.ref

java.lang.ref包规范(参看JDK API中所述内容,本文就不贴出来了)有几个点很重要。

1. 这个包中的类使得应用程序可以与JVM垃圾收集器进行一些交互;

2. 引用的可达性逐渐降低:强引用、弱引用、软引用、虚引用;

3. 自动清除引用:只有弱引用和软引用会自动清除引用(这表明虚引用不会自动清除),清除的时机是将引用注册到引用队列之前(只有当内存不够用,软引用才会被回收;无论内存够不够用,只要发生垃圾回收,弱引用都会被回收);

4. 虚引用不会自动清除引用,当一个虚引用被认为是一定会被垃圾回收器回收的时候,这个虚引用才会被注册到引用队列,而不会像软引用和弱引用必须等到垃圾回收器回收之后才会被注册到引用队列;

解决:

1. 验证弱引用和软引用的自动清除;

2. 侧面说明虚引用注册时机——什么是一定会被垃圾回收器回收;

二、验证准备

1. 验证方法介绍

a. 选择java.lang.ref.Reference中的方法isEnqueued来验证当前引用是否已经进入引用队列;清晰的逻辑还需要知道一个方法,即enqueue,这个方法会将当前引用放入队列并修改当前引用的队列为ReferenceQueueENQUEUED,整个原理很简单,剩余的代码就不贴出来了。

b. 当一个引用已经进入队列,则可以用调用java.lang.ref.ReferenceQueue中的方法poll来将引用出队列,特别注意的是,当一个引用出队列的时候,他自身关联的引用队列会再一次被修改(上一次是进入队列的时候),整个思想可以这么来说,“不惹毛我的时候我们是朋友(引用和引用队列是依赖关系),惹毛了我就搞你(进入队列时候第一次被修改,引用不再依赖于引用队列),搞完你了谁也不认识谁(出队列的时候第二次修改)”,其实引用在出列的时候就没有存在的必要了,但是引用队列可能还被其他引用依赖,因此出队列的引用要显式的Reference=null。

2. 验证类介绍

准备一个类,不重写finalize方法、重写finalize方法、重写的finalize方法产生this逃逸。

3. 知识铺垫

本文所涉及的关于垃圾回收的小知识补充。

在《深入java虚拟机(周志明著)》一书中垃圾收集算法“可达性分析”(用来陈述什么样的对象会被垃圾回收),当一个对象被认为是不可达(可达、可恢复、不可达三种状态)状态时,该对象就会被垃圾回收。JVM判断一个对象为不可达,一是该对象不存在强引用,二是是否有必要调用该对象的finalize方法(一个对象生命周期中只会被调用一次,千万记住,该方法只会被调用一次),因为如果重写了Object中的finalize方法,重写逻辑中有可能会使得该对象变成可达状态,那么该对象将不会进行来及回收。

是否有必要调用该对象的finalize方法,当该对象的类没有重写Object的finalize方法或该对象的finalize方法已经被调用过,则JVM认为不必调用,该对象会立即认为是不可达的;稍微复杂一点的情况是,一个对象的类重写了Object的finalize方法且尚未被调用过,则该对象会被放入一个叫做F-QUEUE的低优先级队列中,等待被执行finalize方法,如果finalize方法被执行之后,该对象依旧不可达,则该对象进入不可达状态,等待被垃圾回收,如果finalize方法被执行后该对象变为可达状态(finalize方法this逸出问题),则该对象不会被垃圾回收,对象变为可达状态。

三、PhantomReference

1. 自动清除

重不重写finalize方法都可以,只要不发生finalize逃逸,则内存一定会被回收,但是千万要注意的是,如果用String类来做验证类,可能得不到你想要的结果,因为JVM内建字符串池机制的存在会导致字符串池强引用的存在,因此不会被垃圾回收,建议使用其他类做验证类。

String做测试和自定义类做测试的结果,如下图所示,String对象没有被垃圾回收,因此不会被加入队列。

2. 虚引用

a. 不重写finalize方法

2. 重写finalize方法

3. 当finalize方法发生this逃逸

四、这才是虚引用

不像软引用、弱引用会自动回收内存,虚引用的存在(虽然内存还是会被回收)更倾向于发送通知,当一个对象确定会被回收之后(此时虚引用中的引用对象并不能确定是否已经被回收内存了,而软引用和弱引用一定是被回收内存了的),就会向应用程序发送一个通知(进入队列和出队列),“我要被清理了,你们是否要做些什么事情呢?”。

所以,虚引用用来做对象清理工作,比finalize方法再好不过了,不会导致垃圾回收器额外做工作,配合Reference阻塞方法remove就能更及时做清理工作。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 12:15:35

【J2SE】这才是java虚引用(PhantomReference)的相关文章

java中虚引用PhantomReference与弱引用WeakReference(软引用SoftReference)的差别

之前的这篇博客介绍了java中4种引用的差别和使用场景,在最后的总结中提到: "软引用和弱引用差别不大,JVM都是先把SoftReference和WeakReference中的referent字段值设置成null,之后加入到引用队列:而虚引用则不同,如果某个堆中的对象,只有虚引用,那么JVM会将PhantomReference加入到引用队列中,JVM不会自动将referent字段值设置成null".这段总结写的比较仓促,也没有给出实际的例子加以佐证.本文主要是重申下这几种引用的差别,并

Java基础篇 - 强引用、弱引用、软引用和虚引用

前言 Java执行GC判断对象是否存活有两种方式其中一种是引用计数. 引用计数:Java堆中每一个对象都有一个引用计数属性,引用每新增1次计数加1,引用每释放1次计数减1. 在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于(reachable)可达状态,程序才能使用它. 从JDK 1.2版本开始,对象的引用被划分为4种级别,从而使程序能更加灵活地控制对象的生命周期.这4种级别由高到低依次为:强引用.软引用.弱引用和虚引用. 正文 (一

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

整体结构 java提供了4中引用类型,在垃圾回收的时候,都有自己的各自特点. 为什么要区分这么多引用呢,其实这和Java的GC有密切关系. 强引用(默认支持模式) 把一个对象赋给一个引用变量,这个引用变量就是一个强引用. 强引用是我们最常见的普通对象引用,只要还有强引用指向一个对象,就能表明对象还活着 当内存不足的时候,jvm开始垃圾回收,对于强引用的对象,就算出现OOM也不会回收该对象的. 因此,强引用是造成java内存泄露的主要原因之一. 对于一个普通的对象,如果没有其他的引用关系,只要超过

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

***********************************************声明****************************************************** 原创作品,出自 "晓风残月xj" 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj). 由于各种原因,可能存在诸多不足,欢迎斧正! *******************************************

弱引用、软引用、虚引用以及强引用

如果一个对象只有弱引用指向它,垃圾回收器会立即回收该对象,这是一种急切回收方式.相对的,如果有软引用指向这些对象,则只有在JVM需要内存时才回收这些对象.弱引用和软引用的特殊行为使得它们在某些情况下非常有用.例如:软引用可以很好的用来实现缓存,当JVM需要内存时,垃圾回收器就会回收这些只有被软引用指向的对象.而弱引用非常适合存储元数据,例如:存储ClassLoader引用.如果没有类被加载,那么也没有指向ClassLoader的引用.一旦上一次的强引用被去除,只有弱引用的ClassLoader就

集合总结:WeakHashMap + 强/软/弱/虚引用

转自:Java极客技术公众号 在 Map 家族中,WeakHashMap 是一个很特殊的成员,从名字上看与 HashMap 相关,但是与 HashMap 有着很大的差别,翻译成中文后表示弱 HashMap,俗称缓存 HashMap. 01.摘要 在集合系列的第一章,咱们了解到,Map 的实现类有 HashMap.LinkedHashMap.TreeMap.IdentityHashMap.WeakHashMap.Hashtable.Properties 等等. 本文主要从数据结构和算法层面,探讨

Java容器-引用分类与部分Map用法

一.目录 1.引用分类 2.了解WeakHashMap.IdentityHashMap.EnumMap 3.同步控制与只读设置 二.代码实现 1.引用分类(面试) 强引用(StrongReference):引用指向对象,gc运行时,不回收. 弱引用(SoftReference):gc运行时可能回收(当jvm内存不足时). 软引用(WeakReference):当gc运行时,对象回收. 虚引用(phantomReference):类似于无银用,主要跟踪对象被回收的对象,不能单独使用,要与Refer

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

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

Java中强、软、弱、虚引用

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