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. 无法控制传入的回收执行逻辑,可能导致性能问题。
相关推荐
程序员码歌37 分钟前
明年35岁了,如何破局?说说心里话
android·前端·后端
橙*^O^*安1 小时前
Go 语言基础:变量与常量
运维·开发语言·后端·golang·kubernetes
BillKu1 小时前
推荐 Eclipse Temurin 的 OpenJDK
java·ide·eclipse
Morri31 小时前
[Java恶补day53] 45. 跳跃游戏Ⅱ
java·算法·leetcode
悟能不能悟1 小时前
eclipse怎么把项目设为web
java·eclipse
工程师小星星1 小时前
Golang语言的文件组织方式
开发语言·后端·golang
乂爻yiyao1 小时前
java 代理模式实现
java·开发语言·代理模式
2301_770373732 小时前
Java集合
java·开发语言
哈喽姥爷2 小时前
Spring Boot---自动配置原理和自定义Starter
java·spring boot·后端·自定义starter·自动配置原理
舒一笑3 小时前
为什么where=Version就是乐观锁了?
后端·mysql·程序员