核心类图
+-----------------------------+ +----------------------------------+
| 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()
方法便于资源泄漏检测