Cleaner:Java的一种新资源释放方式

引言

在JDK9中新增了Cleaner类,该类的作用是用于替代finalize方法,更有效地释放资源并避免内存泄漏。

基本概念和使用

JEP260提案中,封装了大部分Sun包内部的API之余,还引入了一些新的API,其中就包含着Cleaner这个工具类。
Cleaner承担着替换finalize方法的作用,为了解决finalize方法的性能问题、安全问题以及不可靠。

Cleaner 类的主要方法和属性

Cleaner类中,一共就三个外部方法,一个简单的工具类。

其中,在调用create方法时,就会新建一条线程,用于监听目标对象是否已经被回收。监听的逻辑则是用到了虚引用 以及引用队列 ,在虚引用中,要是一个对象变成不可达后,在GC前会将该对象的虚引用放入引用队列中。详细的步骤以及逻辑可以看这篇文章【Java引用规范】虚引用以及引用队列

如何创建和使用 Cleaner 对象

  1. 使用Cleaner.create()创建Cleaner对象。
  2. 调用cleaner.register()方法,传入监听的对象以及回收后要执行的逻辑。其中,逻辑中不能带有监听对象的引用,否则对象将永远无法被回收。

实际应用和示例

典型的 Cleaner 类使用场景和示例代码

在JDK1.2中,就已经有这个类的内部实现了,不过是在sun包中实现的。由于是内部类不建议在生产代码中直接使用。不过sun包下的Cleaner类和lang包下的Cleanr类的功能是类似的。

Cleaner在JDK中最典型的实现就是堆外内存的回收。我们申请到一个堆外内存后,是无法手动将该堆外内存进行显示的回收的,只能等待JVM来自动回收该内存。

其中,自动回收的操作就是使用到了Cleaner工具类,在DirectByteBuffer的构造方法中,申请到堆外内存后,就会将堆外内存地址、申请容量 以及实际内存大小 传入到Deallocator类中进行空间的回收。

Deallocator类集成了Runnable接口,在run方法中就会将对应地址的堆外内存回收。

优点和局限性

Cleaner 类相比 Finalizer 和 PhantomReference 的优势

类型 自动化清理 易用性 安全性 性能影响
Cleaner 开箱即用 更强 较小
Finalizer 开箱即用 较弱 较大
PhantomReference 需要与引用队列相结合,额外代码工作量 较弱 较小

Cleaner 类和手动调用Close方法的区别

操作 执行时机 确定性 是否自动化清理 资源泄漏风险
Cleaner 对象被回收时隐式调用 执行时机无法控制 低(只要对象不再可达,就会自动清理)
调用Close方法 代码显示调用 只要调用,一定执行 高(如果忘记调用 close 方法,可能会导致资源泄露)

Cleaner 类的潜在问题和限制

  1. 每注册一个Cleaner类,就会新开一条线程用于监听目标对象是否已经进入到引用队列。直到目标对象被回收后,新线程才结束。
  2. Cleaner回收时间点无法控制。
  3. 不能替换所有的资源释放,必要时还是需要显式执行Close方法。
  4. 无法控制传入的回收执行逻辑,可能导致性能问题。
相关推荐
刃神太酷啦2 分钟前
聚焦 string:C++ 文本处理的核心利器--《Hello C++ Wrold!》(10)--(C/C++)
java·c语言·c++·qt·算法·leetcode·github
日月星辰Ace12 分钟前
Java JVM 浅显理解
java·jvm
用户984089050872412 分钟前
Java集合 ArrayList 多线程下报错ArrayIndexOutOfBoundsException
java
小巫程序Demo日记13 分钟前
SparkUI依赖问题解决方法
java·spark
xiaoming001814 分钟前
Django中使用流式响应,自己也能实现ChatGPT的效果
后端·python·chatgpt·django
满分观察网友z14 分钟前
我与Java IO的爱恨情仇:从“文件复制等到天荒地老”到“对象序列化秒存秒取”的顿悟之旅
后端
满分观察网友z15 分钟前
乱码、卡顿、崩溃?我用 Java IO '流'操作,搞定一个棘手的实时日志系统!
后端
武子康16 分钟前
大数据-14-Hive HQL 表连接查询 HDFS导入导出 逻辑运算 函数查询 全表查询
大数据·后端·apache hive
星辰大海的精灵16 分钟前
轻松玩转 Kubernetes 集群的工具包
后端·架构·kubernetes
import_random29 分钟前
[python]Flask(介绍+应用)
后端