Java引用类型
Java中有四种引用类型。其中SoftReference、WeakReference、PhantomReference构造时都可以指定ReferenceQueue,当目标对象 (Referent) 被回收时,Reference会被添加到队列中。
| 中文 | 英文 | 取得目标对象 (Referent) 方式 | 垃圾回收条件 | ReferenceQueue构造参数 |
|---|---|---|---|---|
| 强引用 | StrongReference | 直接调用 | 不回收 | - |
| 软引用 | SoftReference | get方法 | gc且内存不足时回收 | 可选参数 |
| 弱引用 | WeakReference | get方法 | gc时回收 | 可选参数 |
| 虚引用 | PhantomReference | 无法取得,get方法始终返回null | gc时回收 | 必传参数 |
使用的坑
注意软引用 / 弱引用的一个坑:
1 | String s = "string"; |
应用
SoftReference、WeakReference都可以用作缓存,例如Glide图片库使用了WeakReference缓存。
WeakReference还可以用于监控内存,例如LeakCanary。
PhantomReferences和WeakReference类似,区别是PhantomReferences不能获取到目标对象。
PhantomReferences的两种作用:
- 监控对象是否已回收,以便实现内存敏感的需求,例如可以等待大对象回收后再创建下一个。
- 代替finalize方法,自行执行回收操作,减小gc压力。
例:LeakCanary在Android中监控内存泄露
LeakCanary可用于检测Android内存泄露,内存追踪使用了WeakReference。
基于LeakCanary 1.5.4源码,流程描述如下:
ActivityRefWatcher:Activity.onDestroy()时,添加Activity对象到RefWatcher监控列表中(创建一个虚引用)。AndroidWatchExecutor:延时5s。RefWatcher:通过ReferenceQueue,判断对象是否已回收。GcTrigger:如果没有回收,触发gc。RefWatcher:判断对象是否已回收。AndroidHeapDumper:如果没有回收,可能有内存泄露。调用Android提供的Debug.dumpHprofData(),生成Heap Dump(堆转储文件)。HeapAnalyzerService:调用haha模块分析内存泄露。
参考: LeakCanary 源码解析
例:PhantomReferences代替finalize方法执行回收操作
Java对象在被gc回收时,finalize方法会被调用。如果在finalize中执行了复杂的任务,会增加gc压力,因此可以借助PhantomReferences自行处理。
代码来自 Phantom References in Java
1 | public class LargeObjectFinalizer extends PhantomReference<Object> { |
1 | ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>(); |
如果觉得文章有帮助,欢迎分享转发,也欢迎关注我的公众号“搬砖的小明”,及时获取更新