Netty的AbstractReferenceCountedByteBuf源码解析

从前面的类继承关系上面我们知道,它是继承 AbstractByteBuf 的类。它的主要功能是计数,类似于 JVM 内存回收的对象引用计数器,用于跟踪对象的分配和销毁,做自动内存回收使用。

成员变量

该类里面的成员变量如下:

15 abstractreferenctCountedByteBuf 成员变量.png

refCntUpdater 是一个 AtomicIntegerFieldUpdater 类型变量,通过原子的方式对成员变量进行更新等操作,来保证线程安全,消除锁。

refCnt 它是一个 volatile 修饰的字段,用来跟踪对象的引用次数,使用 volatile 是为了解决多线程并发访问的可见性问题。

对象引用计数器

计数器加1

每调用一次 retain 方法,引用计数器就会加 1,因为可能存在多线程并发调用的场景,所以它的累加操作都是原线程安全的,具体代码如下:

private ByteBuf retain0(final int increment) { int oldRef = refCntUpdater.getAndAdd(this, increment); if (oldRef <= 0 || oldRef + increment < oldRef) { // Ensure we don't resurrect (which means the refCnt was 0) and also that we encountered an overflow. refCntUpdater.getAndAdd(this, -increment); throw new IllegalReferenceCountException(oldRef, increment); } return this; }

refCntUpdater 的实现方式通过自旋对引用计数器进行加 1 操作。引用计数器的初始值是 1,如果申请和释放的操作能够保证正确的使用,那么它的最小值就是 1。当被释放和被申请的次数相等的时候,就调用回收方法回收当前的 ByteBuf 对象。如果是 小于等于 0,说明对象被意外错误的地方引用,抛出异常。

计数器减1

调用 release 方法。它和 retain 方法相似,只不过将被减少的数据传递负值,它的源码如下:

private boolean release0(int decrement) { int oldRef = refCntUpdater.getAndAdd(this, -decrement); if (oldRef == decrement) { deallocate(); return true; } else if (oldRef < decrement || oldRef - decrement > oldRef) { // Ensure we don't over-release, and avoid underflow. refCntUpdater.getAndAdd(this, decrement); throw new IllegalReferenceCountException(oldRef, -decrement); } return false; }

它也是通过 CAS 方式对引用计数进行减操作。当 oldRef 和 decrement 相等的时候,说明申请和释放相等,该对象的引用已经不可达了,需要对该对象释放和垃圾回收,所以就调用 deallocate 方法来释放 ByteBuf 对象。

Netty的AbstractReferenceCountedByteBuf源码解析总结

AbstractReferenceCountedByteBuf 主要是对 ByteBuf 的引用计数操作的,它的增和减都是自旋操作。