Netty源码深度解析-ByteBuf(1) ByteBuf简介

导读

原创文章,转载请注明出处。

本文源码地址:netty-source-code-analysis

本文所使用的netty版本4.1.6.Final:带注释的netty源码

本文简要地介绍ByteBuf的结构、主要api和创建方法。

1 ByteBuf的结构

每一个ByteBuf都有一个可容纳的字节上限叫capacity。在ByteBuf中通过两个指针readerIndexwriterIndex将整个个ByteBuf划分成3个部分,分别是已丢弃部分可读部分可写部分,示意图如下。

+-------------------+------------------+------------------+
|       已丢弃      |       可读       |      可写        |
|                   |     (CONTENT)    |                  |
+-------------------+------------------+------------------+
|                   |                  |                  |
0      <=      readerIndex   <=   writerIndex    <=    capacity

readerIndexwriterIndexcapacity之间满足简单地数学关系0 <= readerIndex <= writerIndex <= capcity

一个新建的从未进行过读写操作的ByteBufreaderIndexwriterIndex都为0。整个空间都是可写部分。

+---------------------------------------------------------+
|                           可写                          |
|                                                         |
+---------------------------------------------------------+
|                                                         |
0                                                      capacity
readerIndex
writerIndex

现在往其中写入一些数据,写数据的过程会引起writerIndex的移动,writerIndex移动的最大值为capacity,写数据的过程中readerIndex保持不变。

+--------------------------------------+------------------+
|                  可读                |      可写        |
|               (CONTENT)              |                  |
+--------------------------------------+------------------+
|                                      |                  |
0                   <=            writerIndex    <=    capacity
readerIndex

接着读取一些数据,读数据的过程会引起readerIndex的移动,readerIndex的最大值为writerIndex,在读数据的过程中writerIndex保持不变。已经被读取过的部分就成了已丢弃部分。

+-------------------+------------------+------------------+
|       已丢弃      |       可读       |      可写        |
|                   |     (CONTENT)    |                  |
+-------------------+------------------+------------------+
|                   |                  |                  |
0      <=      readerIndex   <=   writerIndex    <=    capacity

2 ByteBuf的主要方法

2.1 write族方法

write族方法用来向ByteBuf中写入各种类型的数据,比如writeByteswriteCharwriteInt等。另外支持写入小端字节序数据,比如writeIntLEwriteLongLE等。

write族方法的调用时写入数据的起始位置就是当前writerIndex指向的位置,写入数据会引起writerIndex的移动。

2.2 read族方法

read族方法用来从ByteBuf中读取数据,比如readByteswriteByteswriteLong等。同样也支持读取小端字节序数据,比如readIntLEreadLongLE等。

read族方法的调用会引起readerIndex的移动。

2.3 set族方法

write族方法一样,set族方法同样用来向ByteBuf中写入各种类型的数据。write能写入的数据set也能,比如writeIntsetInt。不同的是set族方法在调用时需要传递一个索引参数,也就是说需要指定写入数据的位置,比如writeInt(int value)setInt(int index, int value)

set族方法的调用不会引起writerIndex的移动。

2.4 get族方法

read族方法一样,get族方法同样用来从ByteBuf中读取数据。比如有getIntgetLong方法。与read族方法不一样的是在调用时需要传递一个索引参数,也就是说需要指定读取数据的位置,比如getInt(int index)readInt()

read族方法的调用不会引起readerIndex的移动。

2.5 读取/设置 Index的方法

ByteBuf提供了writerIndex()readerIndex()方法分别可以返回当前的writerIndexreaderIndex

除了readwrite方法可以改变readerIndexwriterIndexByteBuf也提供了可以手动设置readerIndexreaderIndex(int readerIndex)及手动设置writerIndexwriterIndex(int writerIndex)方法。

2.6 slice方法

slice方法将当前ByteBuf的可读数据区映射到一个新的ByteBuf,并返回这个新的ByteBuf。这个新的ByteBuf与原ByteBuf共享数据区域,但是拥有独立的readerIndexwriterIndex

也提供了slice(int index, int length)方法可以指定映射的数据区域范围。

对新的ByteBuf数据的修改同样会影响到的原来的ByteBuf的数据,反之亦然。

2.7 duplicate方法

duplicate方法将当前ByteBuf的整个数据区映射到一个新的ByteBuf,并返回这个新的ByteBuf。这个新的ByteBuf与原ByteBuf共享数据区域,但是拥有独立的readerIndexwriterIndex

对新的ByteBuf数据的修改同样会影响到的原来的ByteBuf的数据,反之亦然。

2.8 copy方法

copy方法返回当前ByteBuf的一个复制品,新的ByteBuf拥有与原来的ByteBuf不一样的数据区域,readerIndexwriterIndex也是独立的。

同样提供了copy(int index, int length)方法可以指定复制的数据区域范围。

对新的ByteBuf数据的修改不会影响到原来的ByteBuf,反之亦然。

2.9 retain和release方法

ByteBuf使用引用计数法来表示当前ByteBuf被引用的次数,如果一个ByteBuf的被引用次数为0,则释放该ByteBuf对应的内存。

3 ByteBuf的主要实现及创建

ByteBuf的主要实现类图如下图所示,总体上分为PooledUnPooled两类,顾名思义为池化的和非池化的,又根据分配的是直接内存还是堆内存分为HeapByteBufDirectByteBuf

ByteBuf类图

3.1 通过ByteBufAllocator创建

ByteBufAllocator有两个实现分别为PooledByteBufAllocatorUnpooledByteBufAllocator对应分配出来是的PooledByteBufUnpooledByteBuf
PooledByteBufAllocator将在后续的文章中重点分析,而UnpooledByteBufAllocator则比较简单,不再赘述。

3.2 通过包裹ByteBuffer及byte[]创建

使用Unpooled.wrappedBuffer方法可以对jdkButeBufferbyte[]进行包裹创建出一个UnpooledByteBuf

4 总结

ByteBuf主要api有read/write,get/set,slice,duplicate,copy等系列方法。实现类上主要分为UnpooledPooled,并且支持分配HeapByteBufDirectByteBuf


关于作者

王建新,转转架构部服务治理负责人,主要负责服务治理、RPC框架、分布式调用跟踪、监控系统等。爱技术、爱学习,欢迎联系交流。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容