核心類圖
+-----------------------------+ +----------------------------------+
| ReferenceCountUpdater | | AbstractReferenceCountedByteBuf |
| <T extends ReferenceCounted>| | (extends AbstractByteBuf) |
+-----------------------------+ +----------------------------------+
| - updater(): AtomicInteger | | - refCnt: volatile int |
| - unsafeOffset(): long | | - updater: static ReferenceC.. |
+-----------------------------+ +----------------------------------+
| + retain(T, int): T |<---------| + retain(): ByteBuf |
| + release(T, int): boolean |<---------| + release(): boolean |
| + refCnt(T): int |<---------| + refCnt(): int |
| + setRefCnt(T, int): void |<---------| # setRefCnt(int): void |
| # realRefCnt(int): int | | # deallocate(): void (abstract) |
+-----------------------------+ +----------------------------------+▲ ▲| |+----------------------------------------+通過內部匿名類或者子類實現具體操作
AbstractReferenceCountedByteBuf
在AbstractByteBuf基礎上增加了引用計數追蹤和內存生命周期管理能力
核心增強能力
1.?引用計數管理
- 使用
volatile int refCnt
字段存儲引用計數(實際值需通過ReferenceCountUpdater
解碼)。 - 實現了
retain()
和release()
方法用于引用計數的增減 - 委托
ReferenceCountUpdater
處理所有原子操作。
2.?內存生命周期管理
- 當引用計數降為0時,自動觸發抽象方法
deallocate()
(由子類實現具體邏輯)釋放內存 - 提供了訪問性檢查
isAccessible()
,確保已釋放的ByteBuf不被誤用
具體實現能力
引用計數操作
// 增加引用計數
public ByteBuf retain()
public ByteBuf retain(int increment)// 減少引用計數,返回是否已釋放
public boolean release()
public boolean release(int decrement)// 獲取當前引用計數
public int refCnt()
生命周期控制
- 自動內存管理: 當
refCnt
降為0時自動調用deallocate()
- 訪問控制: 通過
isAccessible()
檢查ByteBuf是否仍然有效 - 調試支持: 提供
touch()
方法用于資源泄漏檢測
線程安全保證
- 使用
AtomicIntegerFieldUpdater
確保引用計數操作的原子性 - 通過
ReferenceCountUpdater
統一管理引用計數的更新邏輯
?具體實現機制分析
雙重保障的線程安全設計
// 1. AtomicIntegerFieldUpdater提供CAS操作
private static final AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> AIF_UPDATER =AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");// 2. Unsafe偏移量提供底層內存訪問
private static final long REFCNT_FIELD_OFFSET =ReferenceCountUpdater.getUnsafeOffset(AbstractReferenceCountedByteBuf.class, "refCnt");
引用計數字段定義
// volatile確保可見性,通過updater訪問確保原子性
@SuppressWarnings({"unused", "FieldMayBeFinal"})
private volatile int refCnt;
生命周期管理流程
初始化階段
protected AbstractReferenceCountedByteBuf(int maxCapacity) {super(maxCapacity);updater.setInitialValue(this); // 設置初始引用計數為1
}
引用計數操作
// 增加引用計數
public ByteBuf retain() {return updater.retain(this); // 通過updater執行原子增操作
}// 減少引用計數并判斷是否需要釋放
public boolean release() {return handleRelease(updater.release(this));
}// 自動內存管理
private boolean handleRelease(boolean result) {if (result) {deallocate(); // 引用計數為0時自動調用}return result;
}
訪問控制檢查
boolean isAccessible() {// 非volatile讀取,提供最佳努力的訪問檢查return updater.isLiveNonVolatile(this);
}
ReferenceCountUpdater
ReferenceCountUpdater
雖然是抽象類,但在AbstractReferenceCountedByteBuf
中通過匿名內部類的方式實現:
private static final ReferenceCountUpdater<AbstractReferenceCountedByteBuf> updater =new ReferenceCountUpdater<AbstractReferenceCountedByteBuf>() {@Overrideprotected AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> updater() {return AIF_UPDATER;}@Overrideprotected long unsafeOffset() {return REFCNT_FIELD_OFFSET;}};
-
定位:為引用計數對象(
ReferenceCounted
)提供通用原子操作邏輯。 -
核心功能:
-
引用計數的編碼/解碼(偶數 = 活躍計數,奇數 = 已釋放)。
-
原子性的增加(
retain
)和減少(release
)操作。 -
處理溢出、競爭條件及非法狀態。
-
-
關鍵設計:
-
編碼機制:真實計數 =
rawCnt >>> 1
(rawCnt
為偶數時有效)。 -
初始值:
rawCnt = 2
(表示真實計數為 1)。 -
釋放標志:
rawCnt
為奇數(如 1)表示已釋放。 -
基于
AtomicIntegerFieldUpdater
或Unsafe
實現高效原子操作。
-
引用計數的編碼設計
存儲字段:private volatile int refCnt
。
/** Implementation notes:** For the updated int field:* Even => "real" refcount is (refCnt >>> 1)* Odd => "real" refcount is 0*/
-
偶數:表示對象活躍狀態,真實引用計數 =
rawCnt >>> 1
(無符號右移1位) -
奇數:表示對象已被釋放,真實引用計數為0
-
初始值:
2
(二進制10
),表示真實計數=1(2 >>> 1 = 1
)
引用計數解碼實現
private static int realRefCnt(int rawCnt) {// 快速路徑:常見值2/4直接處理,避免位運算return rawCnt != 2 && rawCnt != 4 && (rawCnt & 1) != 0 ? 0 // 奇數=>已釋放: rawCnt >>> 1; // 偶數=>真實計數
}
增加引用計數(retain
)
public final T retain(T instance, int increment) {int rawIncrement = checkPositive(increment, "increment") << 1; // 增量*2return retain0(instance, increment, rawIncrement);
}private T retain0(T instance, int increment, int rawIncrement) {int oldRef = updater().getAndAdd(instance, rawIncrement);// 檢查對象是否已被釋放(奇數)if (oldRef != 2 && oldRef != 4 && (oldRef & 1) != 0) {throw new IllegalReferenceCountException(0, increment);}// 溢出檢查(整數回繞)if ((oldRef <= 0 && oldRef + rawIncrement >= 0) ||(oldRef >= 0 && oldRef + rawIncrement < oldRef)) {updater().getAndAdd(instance, -rawIncrement); // 回滾操作throw new IllegalReferenceCountException(realRefCnt(oldRef), increment);}return instance;
}
-
操作流程:
-
將增量
increment
左移1位(increment << 1
) -
原子增加字段值(
getAndAdd
) -
檢查原值:
-
若是奇數(已釋放),拋出異常
-
若發生整數溢出,回滾并拋出異常
-
-
減少引用計數(release
)
public final boolean release(T instance, int decrement) {int rawCnt = nonVolatileRawCnt(instance); // 非易失讀(性能優化)int realCnt = toLiveRealRefCnt(rawCnt, decrement); // 解碼并驗證// 關鍵分支:是否釋放到0return decrement == realCnt ? tryFinalRelease0(instance, rawCnt) || retryRelease0(instance, decrement): nonFinalRelease0(instance, decrement, rawCnt, realCnt);
}
最終釋放(歸零)
private boolean tryFinalRelease0(T instance, int expectRawCnt) {// CAS設置奇數(任何奇數均可,1最常用)return updater().compareAndSet(instance, expectRawCnt, 1);
}private boolean retryRelease0(T instance, int decrement) {for (;;) {int rawCnt = updater().get(instance); // 易失讀(確保最新值)int realCnt = toLiveRealRefCnt(rawCnt, decrement);if (decrement == realCnt) { // 需要歸零if (tryFinalRelease0(instance, rawCnt)) return true;} else if (decrement < realCnt) { // 常規釋放int newRawCnt = rawCnt - (decrement << 1);if (updater().compareAndSet(instance, rawCnt, newRawCnt)) {return false;}} else { // 過度釋放throw new IllegalReferenceCountException(realCnt, -decrement);}Thread.yield(); // 高爭用優化}
}
常規釋放(未歸零)
private boolean nonFinalRelease0(T instance, int decrement, int rawCnt, int realCnt) {// 檢查是否滿足釋放條件if (decrement < realCnt) {int newRawCnt = rawCnt - (decrement << 1); // 計算新值// 嘗試CAS更新if (updater().compareAndSet(instance, rawCnt, newRawCnt)) {return false; // 未觸發釋放}}return retryRelease0(instance, decrement); // 進入重試
}
狀態驗證(防御性檢查)
private static int toLiveRealRefCnt(int rawCnt, int decrement) {// 快速路徑:2/4/6/8或任何偶數if (rawCnt == 2 || rawCnt == 4 || (rawCnt & 1) == 0) {return rawCnt >>> 1;}// 奇數=>已釋放對象throw new IllegalReferenceCountException(0, -decrement);
}
性能優化技巧
非易失讀優先:
private int nonVolatileRawCnt(T instance) {long offset = unsafeOffset();return offset != -1 ? PlatformDependent.getInt(instance, offset) // Unsafe直接讀: updater().get(instance); // 回退到原子讀
}
PlatformDependent 最終調用?Unsafe
??
- ??無內存屏障??:讀取可能不保證其他線程的寫入可見性(除非顯式插入屏障)。
- 類似普通變量讀取,可能觸發??指令重排序??。
??AtomicFieldUpdater
??
- 保證??
volatile
語義??(如AtomicIntegerFieldUpdater
要求字段為volatile
)。 - 讀取前插入??LoadLoad屏障??,確保其他線程的修改可見。
快速路徑優化:在realRefCnt
、toLiveRealRefCnt
中優先檢查常見值(2/4)
爭用處理:釋放失敗時使用Thread.yield()
而非忙等
關鍵設計總結
-
狀態編碼:
-
用奇偶性區分活躍/已釋放狀態
-
真實計數 = 存儲值 / 2
-
-
原子性保證:
-
所有修改通過
AtomicIntegerFieldUpdater
或Unsafe
的CAS實現 -
歸零操作為單次CAS(設置奇數)
-
設計總結
1. 模板方法模式
-
ReferenceCountUpdater
定義算法骨架 -
子類實現具體的
updater()
和unsafeOffset()
方法 -
統一了引用計數的管理邏輯
2. 性能優化
-
雙重實現: 既支持
AtomicIntegerFieldUpdater
又支持Unsafe
直接訪問 -
非volatile讀取:?
isLiveNonVolatile()
避免不必要的內存屏障 -
靜態工廠: 預先創建updater實例,減少運行時開銷
3. 內存安全
- 自動釋放: 引用計數為0時自動調用
deallocate()
- 訪問控制: 通過
isAccessible()
防止使用已釋放的對象 - 調試支持:?
touch()
方法便于資源泄漏檢測