JAVA基础——JAVA的五种引用类型及引用队列

Sophia ·
更新时间:2024-11-10
· 952 次阅读

JAVA 的五种引用类型及引用队列

​ 在介绍 JAVA 的五种引用之前,先介绍一下什么是引用,以及引用和对象之间的关系

什么是引用

​ 众所周知,JAVA 是一种面向对象的语言,在 JAVA 程序运行时,对象是存储在堆内存(Heap)中的,C/C++ 中是通过指针来访问所谓对象(结构体)的,而 JAVA 则是通过引用来访问对象,也就是说,引用指向了对象在堆内存中的地址,引用本身也占用内存,64 位的 JVM 中,引用所占内存大小为 8 个字节,通过指针压缩后占用 4 个字节

​ 在 JDK 1.2 之前,JAVA 对引用的定义为:如果一个数据中存储的数值代表的是另外一块内存的起始地址,就称这块数据的内存代表着一个引用

​ 在 JDK 1.2 之后,JAVA 引用的概念得到了扩充,引用被分为:强引用、软引用、弱引用、虚引用、终结器引用

引用和对象

​ 在 JAVA 中,一切都被视为是对象,但标识符(变量名)实际上是对象的一个引用

//创建一个引用,引用可以独立存在,不是必须要关联某一对象 String str;

​ 也可以将引用指向对象,这样操作后就可以通过引用来操作对象

String str = new String("123"); 垃圾回收算法、五种引用类型及引用队列

​ JAVA 在垃圾回收机制中判断是否要回收某一对象时,都需要引用的概念

引用计数法

​ 引用计数法的原理为:如果变量被引用:计数 +1,没有对象引用计数 -1,为 0 回收,很明显,当一个对象需要被循环引用时,引用计数法可能会存在问题

可达性分析算法

​ Java 虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象:扫描堆中的对象,看是否能够沿着 GC Root 对象为起点的引用链找到该对象,找不到表示可以回收

强引用

​ 只有所有 GC Roots 对象都不通过强引用引用该对象,该对象才能被垃圾回收,换句话说就是,只要强引用存在,JVM 垃圾回收器就永远都不会回收被引用的对象,即使内存不足,JVM 会抛出 OutOfMemoryError

//只要 obj 指向 Object 对象,那它就永远都不会被 JVM 回收 Object obj = new Object(); //将 obj 置为 null,可以切断引用链,这样 obj 就会被 JVM 回收 obj = null; 引用队列

​ ReferenceQueue,当一个引用(软引用、弱引用)关联到了一个引用队列后,当这个引用所引用的对象要被垃圾回收时,就会将它加入到所关联的引用队列中,所以判断一个引用对象是否已经被回收的一个现象就是,这个对象的引用是否被加入到了它所关联的引用队列

ReferenceQueue queue = new ReferenceQueue(); SoftReference ref = new SoftReference(new byte[_4MB], queue);

​ 说到底,引用队列就是一个对引用的回收机制,当软引用或弱引用所包装的对象为 null 或被回收时,这个引用也就不在具有价值,引用队列就是清除掉这部分引用的一种回收机制

软引用

​ 仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次触发垃圾回收,回收软引用对象,即在内存足够时,JVM 不会回收软引用对象,但当内存不足时,软引用对象就会被回收,所以软引用对象通常用来描述一些非必要但仍有用的对象

//不直接通过 list 引用 byte[] //list -----> SoftReference -----> byte[] 添加了一层软引用 List<SoftReference> list = new ArrayList(); 弱引用

​ 弱引用是较软引用更第一级的引用,只要发生垃圾回收,无论内存是否充足,JVM 都会回收掉弱引用对象

List<WeakReference> list = new ArrayList(); 虚引用

​ 虚引用必须配合引用队列使用,主要配合 ByteBuffer 使用,被引用对象回收时,会将虚引用入队,由 Reference Handler 线程调用虚引用相关方法释放直接内存

终结器引用

​ 终结器引用无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由 Finalizer 线程通过终结器引用找到被引用对象并调用 finalize 方法,第二次 GC 时回收被引用对象


作者:scfor333



JAVA java的 java基础 队列 引用类型

需要 登录 后方可回复, 如果你还没有账号请 注册新账号