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框架、分布式调用跟踪、监控系统等。爱技术、爱学习,欢迎联系交流。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容