Netty - ByteBuf (3)

1. Netty - ByteBuf (3)

1.3 ByteBuf相关实现源码

相关类继承关系
这里写图片描述
其中,我们从AbstractByteBuf和他的子类开始分析,其他的多为衍生工具类。

1.3.1. AbstractByteBuf

上一节主要的源代码都是AbstractByteBuf中的,这里不再赘述其中的方法,其中的域如下所示:
这里写图片描述
其中有一个ResourceLeakDetector,用了装饰器模式实现,用于检测内存泄露(没有成对调用ByteBuf的retain和relaease方法,导致ByteBuf没有被正常释放),这里先跳过。
SwappedBytebuf用于翻转ByteBuf,也用了装饰器模式实现。

1.3.2. AbstractReferenceCountedByteBuf ->AbstractByteBuf

接下来看AbstractByteBuf的一个子类,AbstractReferenceCountedByteBuf 。这是用来做ByteBuf引用计数的类。这个引用计数用来跟踪内存的分配和销毁,以便于内存回收和检测内存泄露。
这里写图片描述
这里用到了原子更新字段类,AtomicIntegerFieldUpdater用于原子更新AbstractReferenceCountedByteBuf 的refCnt字段。refCnt就是引用计数。
静态初始化:

static {
//首先通过netty运用Unsafe创建AtomicIntegerFieldUpdater
    AtomicIntegerFieldUpdater<AbstractReferenceCountedByteBuf> updater =
            PlatformDependent.newAtomicIntegerFieldUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
    //若创建不成功
    if (updater == null) {
        updater = AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");
    }
    refCntUpdater = updater;
}

这里有个netty的PlatformDependent类,用于检测运行环境,以及是否用java的Unsafe这个类。这个类是用于执行低级别、不安全操作的方法集合。尽管这个类和所有的方法都是公开的(public),但是这个类的使用仍然受限,你无法在自己的java程序中直接使用该类,因为只有授信的代码才能获得该类的实例。该类是用来执行较低级别的操作的,比如获取某个属性在内存中的位置等等,还有一些底层的IO操作。Java 8可能会将Unsafe剔除,netty通过设置“io.netty.noUnsafe”这个系统属性为true或false来开启或关闭使用Unsafe。
PlatformDependent.java:

/**
     * Create a new optimized {@link AtomicIntegerFieldUpdater} or {@code null} if it
     * could not be created. Because of this the caller need to check for {@code null} and if {@code null} is returned
     * use {@link AtomicIntegerFieldUpdater#newUpdater(Class, String)} as fallback.
     */
    public static <T> AtomicIntegerFieldUpdater<T> newAtomicIntegerFieldUpdater(
            Class<?> tclass, String fieldName) {
        if (hasUnsafe()) {
            try {
                return PlatformDependent0.newAtomicIntegerFieldUpdater(tclass, fieldName);
            } catch (Throwable ignore) {
                // ignore
            }
        }
        return null;
    }

PlatformDependent只是一个对外的暴露的类,真正的实现是
PlatformDependent:
PlatformDependent.java

static <T> AtomicIntegerFieldUpdater<T> newAtomicIntegerFieldUpdater(
            Class<?> tclass, String fieldName) throws Exception {
        return new UnsafeAtomicIntegerFieldUpdater<T>(UNSAFE, tclass, fieldName);
    }

netty运用Unsafe自己实现的优化的UnsafeAtomicIntegerFieldUpdater:

final class UnsafeAtomicIntegerFieldUpdater<T> extends AtomicIntegerFieldUpdater<T> {
    private final long offset;
    private final Unsafe unsafe;

    UnsafeAtomicIntegerFieldUpdater(Unsafe unsafe, Class<?> tClass, String fieldName) throws NoSuchFieldException {
        Field field = tClass.getDeclaredField(fieldName);
        if (!Modifier.isVolatile(field.getModifiers())) {
            throw new IllegalArgumentException("Must be volatile");
        }
        this.unsafe = unsafe;
        offset = unsafe.objectFieldOffset(field);
    }

    @Override
    public boolean compareAndSet(T obj, int expect, int update) {
        return unsafe.compareAndSwapInt(obj, offset, expect, update);
    }

    @Override
    public boolean weakCompareAndSet(T obj, int expect, int update) {
        return unsafe.compareAndSwapInt(obj, offset, expect, update);
    }

    @Override
    public void set(T obj, int newValue) {
        unsafe.putIntVolatile(obj, offset, newValue);
    }

    @Override
    public void lazySet(T obj, int newValue) {
        unsafe.putOrderedInt(obj, offset, newValue);
    }

    @Override
    public int get(T obj) {
        return unsafe.getIntVolatile(obj, offset);
    }
}

这个原子更新类字段变量更新refCnt字段。
调用retian(),就是获取对于这个AbstractReferenceCountedByteBuf的引用。引用计数器加一。

public ByteBuf retain() {
    for (;;) {
        int refCnt = this.refCnt;
        //如果引用计数器为0,这是不符合逻辑的,refCnt 初始为1,如果调用了正常次数的获取释放,引用计数器最小为1
        if (refCnt == 0) {
            throw new IllegalReferenceCountException(0, 1);
        }
        if (refCnt == Integer.MAX_VALUE) {
            throw new IllegalReferenceCountException(Integer.MAX_VALUE, 1);
        }
        //CAS尝试更新refCnt为refCnt+1,如果更新成功则退出循环,否则继续更新
        if (refCntUpdater.compareAndSet(this, refCnt, refCnt + 1)) {
            break;
        }
    }
    return this;
}

public ByteBuf retain(int increment) {
        if (increment <= 0) {
            throw new IllegalArgumentException("increment: " + increment + " (expected: > 0)");
        }

        for (;;) {
            int refCnt = this.refCnt;
            if (refCnt == 0) {
                throw new IllegalReferenceCountException(0, increment);
            }
            if (refCnt > Integer.MAX_VALUE - increment) {
                throw new IllegalReferenceCountException(refCnt, increment);
            }
            if (refCntUpdater.compareAndSet(this, refCnt, refCnt + increment)) {
                break;
            }
        }
        return this;
    }

对应的,release()就是释放

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值