OceanBase 产品体系
2026/7/29 20:26:08
说明:本文围绕 Java 的四类引用(强、软、弱、虚),结合 GC 可达性模型与 OpenJDK 源码,实现“知其然更知其所以然”。文末附权威参考与速记口诀。
多引用模型源于 Java 对 GC 语义的抽象:通过ReferenceAPI提供“对象可达性”和“回收时机”的可控协作机制,兼容不同 GC 实现(Serial、Parallel、G1、ZGC、Shenandoah 等)。设计目标:
ReferenceQueue与清理通道以避免传统终结器带来的不确定性。-XX:SoftRefLRUPolicyMSPerMB影响(不同版本/GC有差异)。WeakHashMap键。ReferenceQueue配合。java.lang.ref包含:Reference、SoftReference、WeakReference、PhantomReference、ReferenceQueue、Cleaner 等。以下以“可读化伪源码 + 行级注释”方式拆解关键逻辑(不同 JDK 版本实现细节略有差异,建议以当前版本源码为准)。
// 可读化伪源码(基于 OpenJDK 思路,删减非核心细节)packagejava.lang.ref;publicabstractclassReference<T>{// 被引用目标;GC 可在不同阶段清除它Treferent;// 引用队列:当引用被清除/可处理时放入此队列ReferenceQueue<?superT>queue;// 链表指针,用于 GC 批处理发现与入队(内部使用)Reference<T>next;// 标记是否已入队booleanenqueued;protectedReference(Treferent){this.referent=referent;}publicTget(){// 强/软/弱引用在未清除前返回对象;虚引用固定返回 nullreturnthis.referent;}publicvoidclear(){// 主动清除引用,释放对目标的可达性this.referent=null;}publicbooleanenqueue(){// 将引用入队以便应用线程消费if(queue!=null&&!enqueued){enqueued=true;// 省略具体链表操作,实际会连接到队列尾returntrue;}returnfalse;}publicbooleanisEnqueued(){returnenqueued;}}referent是被 GC 关注的目标;清除它意味着“引用不再保持对象”。queue用于与应用代码协作处理“清理事件”。get()的统一行为:除虚引用以外,若尚未被清除则返回对象。clear()主动释放,可与资源关闭逻辑搭配。enqueue()入队是异步处理的桥梁,避免在 GC 线程直接执行用户逻辑。publicclassSoftReference<T>extendsReference<T>{publicSoftReference(Treferent){super(referent);}publicSoftReference(Treferent,ReferenceQueue<?superT>q){super(referent);this.queue=q;}// get() 继承父类,内存紧张或 GC 策略触发时,referent 可能被清除}-XX:SoftRefLRUPolicyMSPerMB调整清除速度,现代 GC 对该参数支持与行为可能变化,请以“当前 JDK + 当前 GC 文档”为准。publicclassWeakReference<T>extendsReference<T>{publicWeakReference(Treferent){super(referent);}publicWeakReference(Treferent,ReferenceQueue<?superT>q){super(referent);this.queue=q;}// 一旦仅弱可达,在最近一次 GC 中必清除}WeakHashMap的键不阻止条目回收。publicclassPhantomReference<T>extendsReference<T>{publicPhantomReference(Treferent,ReferenceQueue<?superT>q){super(referent);this.queue=q;}@OverridepublicTget(){returnnull;}// 固定返回 null}get()永远为 null,表明对象已不再对应用可用;更适合编排“回收后”的外部资源清理(文件句柄、native 内存等)。publicclassReferenceQueue<T>{privateReference<?extendsT>head;publicReference<?extendsT>poll(){// 非阻塞获取队首varr=head;if(r!=null){head=r.next;r.next=null;}returnr;}publicReference<?extendsT>remove()throwsInterruptedException{// 阻塞等待(省略等待实现)while(true){varr=poll();if(r!=null)returnr;// wait/park 省略}}}poll()非阻塞消费,适合在后台线程轻量轮询。remove()阻塞等待,适合“必须处理”型清理。WeakHashMap:键用弱引用,值通常仍需强引用持有或具备外部生命周期管理。get()永远 null,虚引用只用于“事件编排”。ReferenceQueue<ByteBuffer>q=newReferenceQueue<>();PhantomReference<ByteBuffer>pr=newPhantomReference<>(buffer,q);// ... 业务逻辑 ...Reference<?extendsByteBuffer>r=q.remove();// 阻塞等待// 执行外部资源清理逻辑,例如释放 DirectByteBuffer 的 native 内存句柄(示意)