AbstractByteBuf源码分析

1.成员变量

 static final ResourceLeakDetector<ByteBuf> leakDetector = new ResourceLeakDetector<ByteBuf>(ByteBuf.class);

    int readerIndex;
    int writerIndex;
    private int markedReaderIndex;
    private int markedWriterIndex;
    private int maxCapacity;
    private SwappedByteBuf swappedBuf;

readerIndex,writeIndex,markedReaderIndex,markWriterIndex,maxCapacity这些都是很平常的变量。
而它的这两个属性,应该引起我们的注意:
一个是SwappedByteBuf swappedBuf;
这个是大端序列与小端序列的转换。

二个是ResourceLeakDetector
这个是Netty用来解决内存泄漏检测机制,非常重要。

由于AbstractByteBuf它继承了抽象类ByteBuf,所以它”不得不”把它的所有琐琐碎碎的函数给实现了,大部分都是一些返回信息的函数,这里就不再赘述,直接上难点!

2.读操作簇

这里写图片描述

取其中之一进行分析吧

 @Override
    public ByteBuf readBytes(ByteBuf dst, int dstIndex, int length) {
        checkReadableBytes(length);
        getBytes(readerIndex, dst, dstIndex, length);
        readerIndex += length;
        return this;
    }

每个读操作都会先调用checkReadableBytes(length);检查是否可读

protected final void checkReadableBytes(int minimumReadableBytes) {
        ensureAccessible();
        if (minimumReadableBytes < 0) {
            throw new IllegalArgumentException("minimumReadableBytes: " + minimumReadableBytes + " (expected: >= 0)");
        }

        if (readerIndex > writerIndex - minimumReadableBytes) {
         throw new IndexOutOfBoundsException(String.format(
                    "readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s",
                    readerIndex, minimumReadableBytes, writerIndex, this));
        }
    }
protected final void ensureAccessible() {
   if (refCnt() == 0) {
        throw new IllegalReferenceCountException(0);
        }
    }

这个函数非常简单,先检查计数器refcnt是否等于0,等于零说明被错误地引用,然后检查传进去的长度参数,小于零抛出错误,加上readIndex大于writeIndex也会抛出错误。

之后会调用getBytes(readerIndex, dst, dstIndex, length);方法,点进去看一看
发现他是父类的抽象方法

 public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length);

为什么没有实现这个方法呢,原因很简单,getBytes方法根据调用函数的对象的不同会采取不同策略,这个函数调用对象可以是一个内存中的ByteBuf也可以是一个堆中的ByteBuf,所以它就没实现罗。

3.写操作簇

有人问,读和写不是差不多嘛,其实不然,写操作有个不同之处,他可以动态扩展内存,是非常值得我们学习的地方。在随便找一个写操作的函数进行一番分析

 @Override
    public ByteBuf writeBytes(ByteBuf src, int srcIndex, int length) {
        ensureAccessible();
        ensureWritable(length);
        setBytes(writerIndex, src, srcIndex, length);
        writerIndex += length;
        return this;
    }

ensureAccessible()检查计数器是否为零, ensureWritable(length);检查是否可读,这个方法的厉害之处在于它可以动态扩展缓存区。
上代码!

 @Override
    public ByteBuf ensureWritable(int minWritableBytes) {
        if (minWritableBytes < 0) {
            throw new IllegalArgumentException(String.format(
                    "minWritableBytes: %d (expected: >= 0)", minWritableBytes));
        }

        if (minWritableBytes <= writableBytes()) {
            return this;
        }

        if (minWritableBytes > maxCapacity - writerIndex) {
            throw new IndexOutOfBoundsException(String.format(
                    "writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",
                    writerIndex, minWritableBytes, maxCapacity, this));

        int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);

        // Adjust to the new capacity.
        capacity(newCapacity);
        return this;
    }

1.如果长度参数小于零,抛出错误。
2.如果长度小于可读长度(capacity() - writerIndex),老铁没毛病,过去吧。
3.如果长度大于最大可读长度(maxCapacity - writerIndex),对不起,抛出错误。
4.最重要的情况大于可读长度小于最大可读长度

capacity() - writerIndex< n <maxCapacity - writerIndex

这时候需要动态扩展长度了,看回这段代码

int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);

        // Adjust to the new capacity.
        capacity(newCapacity);
        return this;

我们在他的父类ByteBuf中看到alloc()返回这个ByteBuf的分配者对象,所以先用分配者对象调用calculateNewCapacity计算出一个适合的新的容量capacity。
然后调用 capacity(newCapacity)设置新的容量,点进去看一看!发现还是父类的方法

 public abstract ByteBuf capacity(int newCapacity);

和上面的getBytes()方法一样没有实现,是不是和这个方法一样和ByteBuf是内存中的还是堆中的有关系呢?
没错,就是这样,capacity(newCapacity)进行扩容处理,当然会因为它的位置而采取不同的处理啊!

代码读到这里,感觉十分行云流水,没有什么地方特别难懂,下一个就是AbstractReferenceCountedByteBuf类了,从名字一看就知道是和计数器有关,肯定不难!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值