❃博主首页 :

「码到三十五」 ,同名公众号 :「码到三十五」

♝博主的话 :

搬的每块砖,皆为峰峦之基;公众号搜索「码到三十五」关注这个爱发技术干货的coder,一起筑基


在Netty这个高性能网络编程框架中,引用计数是一种重要的内存管理机制,用于确保资源(如ByteBuf)在不再被需要时能够被及时释放,从而避免内存泄漏。Netty通过ReferenceCounted接口、AbstractReferenceCountedByteBuf抽象类以及ReferenceCountUpdater工具类实现了这一机制。本文将结合Netty的源码,详细介绍这三个类的工作原理。

一、ReferenceCounted接口

ReferenceCounted接口是Netty中引用计数机制的核心接口,它定义了与引用计数相关的基本操作。当一个对象实现了ReferenceCounted接口,就意味着它具备了引用计数的能力。接口中的关键方法包括:

  • retain(): 增加引用计数,通常默认增加1。
  • retain(int increment): 按指定增量增加引用计数。
  • release(): 减少引用计数,通常默认减少1。如果引用计数降至0,则对象将被显式释放。
  • release(int decrement): 按指定递减量减少引用计数,如果引用计数降至0,则对象被释放。
  • refCnt(): 返回当前对象的引用计数。

这些方法的实现通常依赖于具体的子类,但接口为所有引用计数对象提供了统一的行为标准。

二、AbstractReferenceCountedByteBuf抽象类

AbstractReferenceCountedByteBufByteBuf的一个抽象子类,它实现了ReferenceCounted接口,为ByteBuf的引用计数提供了具体的实现框架。这个类通过维护一个引用计数字段来跟踪ByteBuf的引用状态,并提供了对ReferenceCounted接口方法的默认实现。

关键特性
  1. 引用计数字段AbstractReferenceCountedByteBuf中通常包含一个volatile int refCnt字段,用于存储引用计数。volatile关键字确保了多线程环境下引用计数的可见性。
  2. 构造方法:在创建AbstractReferenceCountedByteBuf对象时,引用计数通常被初始化为1,表示对象被创建时即有一个引用。
  3. retain和release方法retain()release()方法通过原子操作更新引用计数。retain()方法会增加引用计数,而release()方法会减少引用计数。如果release()方法将引用计数减少到0,则对象占用的资源将被释放。
代码
public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {
    private volatile int refCnt = 1; // 引用计数初始化为1

    @Override
    public ByteBuf retain() {
        for (;;) {
            int refCnt = this.refCnt;
            if (refCnt == 0) {
                throw new IllegalReferenceCountException(0, 1);
            }
            if (refCntUpdater.compareAndSet(this, refCnt, refCnt + 1)) {
                break;
            }
        }
        return this;
    }

    @Override
    public final boolean release() {
        for (;;) {
            int refCnt = this.refCnt;
            if (refCnt == 0) {
                throw new IllegalReferenceCountException(0, -1);
            }
            if (refCntUpdater.compareAndSet(this, refCnt, refCnt - 1)) {
                if (refCnt == 1) {
                    deallocate(); // 释放资源
                    return true;
                }
                return false;
            }
        }
    }

    // 其他方法...
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.

三、ReferenceCountUpdater工具类

ReferenceCountUpdater是一个工具类,它提供了对引用计数进行原子操作的静态方法。由于引用计数通常需要在多线程环境中进行更新,因此原子操作是必需的。ReferenceCountUpdater利用AtomicIntegerFieldUpdater实现了这一功能。

关键方法
  • newUpdater(Class<T> clazz, String fieldName): 创建一个ReferenceCountUpdater实例,用于对指定类的指定字段进行原子更新。
  • incrementAndGet(T instance): 以原子方式增加引用计数并返回新值。
  • decrementAndGet(T instance): 以原子方式减少引用计数并返回新值。
示例用法

AbstractReferenceCountedByteBuf中,ReferenceCountUpdater被用来实现retain()release()方法中的原子操作。虽然具体的示例代码在AbstractReferenceCountedByteBuf中已给出,但这里再次强调ReferenceCountUpdater的作用:它使得在多线程环境下安全地更新引用计数成为可能。

总结

Netty通过ReferenceCounted接口、AbstractReferenceCountedByteBuf抽象类以及ReferenceCountUpdater工具类实现了高效的引用计数机制。这一机制确保了ByteBuf等资源在不再被需要时能够被及时释放,从而避免了内存泄漏问题。开发者在使用Netty进行网络编程时,应当注意合理调用retain()release()方法,以确保引用计数的正确性。同时,Netty还提供了内存泄漏检测等机制,帮助开发者发现和解决潜在的内存管理问题。


关注公众号[码到三十五]获取更多技术干货 !