扩展 - 引用
# 引用
充分理解这些引用,对于我们设计可靠的缓存等框架,或者诊断应用 OOM 等问题,会很有帮助。比如,诊断 MySQL connector-j 驱动在特定模式下(useCompression=true)的内存泄漏问题,就需要我们理解怎么排查幻象引用的堆积问题。
# 强引用
强引用(StrongReference),常见就是普通对象引用就是强引用,只要有引用指向一个对象,就说明该对象是活跃的,垃圾收集机制不会对其进行回收。在对象没有额外的引用时,当对象超过了其引用作用域或者显示地将对象引用赋值为 null,则说明该对象可以被垃圾收集器回收,何时回收取决于垃圾收集策略
# 软引用
软引用(SoftReferenct),相对于强引用弱化一些,可以让对象豁免一下垃圾收集。只有当内存不足时,JVM 才会对软引用指向的对象进行回收,在程序抛出 OutOfMemerryException 前,JVM 会先回收软引用对象。软引用通常应用于对内存敏感的缓存中,内存足够则不清理,不够时再清理部分,从而保证在使用内存的同时不会耗尽内存。
# 弱引用
弱引用(WeekReference)并不能让对象豁免垃圾收集,仅仅表示提供一种在弱引用状态下访问对象的途径。可用于构建没有特定约束的关系,如一个非强制性映射关系,若获取时不存在则重新实例化。常用于缓存机制。
# 幻象引用
幻象引用,不能通过其访问对象,只提供对象在被 finalize 后可以执行某些操作,如 Post-Moterm
# 延伸扩展
- 对象可达性状态流转分析
对象声明周期,不同可达性状态:
强可达(Strongly reachable),表示一个线程或多个线程在不通过引用就可以访问对象的状态,比如创建一个对象,则当前创建对象的线程对该对象就是强可达性。
软可达(Softly reachable):表示只有通过引用才能访问对象的状态
弱可达(Weekly Reachable):只有通过弱引用才能访问对象的状态,当弱引用被清除时就可以进行 finalize
幻象可达(Phantom Reachable):表示没有强引用、软引用、弱引用关联,并且已经 finalize,只有幻象引用执行该对象
不可达(Ureachable):表示该对象可以被清除
判断对象可达性,是 JVM 垃圾收集器如何处理对象的一部分因素。
所有引用类都是 java.ref.Reference 的子类,该父类有个 get 方法用于访问对象,除了幻象引用访问到的都为null(因为对象已经被销毁),而通过软引用和弱引用访问到的对象可以重新指向强引用。
如果我们错误的保持了强引用(比如,赋值给了 static 变量),那么对象可能就没有机会变回类似弱引用的可达性状态了,就会产生内存泄漏。所以,检查弱引用指向对象是否被垃圾收集,也是诊断是否有特定内存泄漏的一个思路,如果我们的框架使用到弱引用又怀疑有内存泄漏,就可以从这个角度检查。
TODO:以下内容暂时待了解,见极客时间 (opens new window)
- 引用队列的使用
- 显式地影响软引用垃圾收集
- 诊断 JVM 引用情况
- Reachability Fence