Netty源码深度解析-ByteBuf(1) ByteBuf简介
导读
原创文章,转载请注明出处。
本文源码地址:netty-source-code-analysis
本文所使用的netty版本4.1.6.Final:带注释的netty源码
本文简要地介绍ByteBuf
的结构、主要api和创建方法。
1 ByteBuf的结构
每一个ByteBuf
都有一个可容纳的字节上限叫capacity
。在ByteBuf
中通过两个指针readerIndex
和writerIndex
将整个个ByteBuf
划分成3个部分,分别是已丢弃部分
、可读部分
和可写部分
,示意图如下。
+-------------------+------------------+------------------+
| 已丢弃 | 可读 | 可写 |
| | (CONTENT) | |
+-------------------+------------------+------------------+
| | | |
0 <= readerIndex <= writerIndex <= capacity
readerIndex
、writerIndex
和capacity
之间满足简单地数学关系0 <= readerIndex <= writerIndex <= capcity
。
一个新建的从未进行过读写操作的ByteBuf
,readerIndex
和writerIndex
都为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
中写入各种类型的数据,比如writeBytes
、writeChar
、writeInt
等。另外支持写入小端字节序数据,比如writeIntLE
、writeLongLE
等。
write
族方法的调用时写入数据的起始位置就是当前writerIndex
指向的位置,写入数据会引起writerIndex
的移动。
2.2 read族方法
read
族方法用来从ByteBuf
中读取数据,比如readBytes
、writeBytes
、writeLong
等。同样也支持读取小端字节序数据,比如readIntLE
、readLongLE
等。
read
族方法的调用会引起readerIndex
的移动。
2.3 set
族方法
和write
族方法一样,set
族方法同样用来向ByteBuf
中写入各种类型的数据。write
能写入的数据set
也能,比如writeInt
和setInt
。不同的是set
族方法在调用时需要传递一个索引参数,也就是说需要指定写入数据的位置,比如writeInt(int value)
和setInt(int index, int value)
。
set
族方法的调用不会引起writerIndex
的移动。
2.4 get
族方法
和read
族方法一样,get
族方法同样用来从ByteBuf
中读取数据。比如有getInt
、getLong
方法。与read
族方法不一样的是在调用时需要传递一个索引参数,也就是说需要指定读取数据的位置,比如getInt(int index)
和readInt()
。
read
族方法的调用不会引起readerIndex
的移动。
2.5 读取/设置 Index的方法
ByteBuf
提供了writerIndex()
和readerIndex()
方法分别可以返回当前的writerIndex
和readerIndex
。
除了read
和write
方法可以改变readerIndex
和writerIndex
,ByteBuf
也提供了可以手动设置readerIndex
的readerIndex(int readerIndex)
及手动设置writerIndex
的writerIndex(int writerIndex)
方法。
2.6 slice方法
slice
方法将当前ByteBuf
的可读数据区映射到一个新的ByteBuf
,并返回这个新的ByteBuf
。这个新的ByteBuf
与原ByteBuf
共享数据区域,但是拥有独立的readerIndex
和writerIndex
。
也提供了slice(int index, int length)
方法可以指定映射的数据区域范围。
对新的ByteBuf
数据的修改同样会影响到的原来的ByteBuf
的数据,反之亦然。
2.7 duplicate方法
duplicate
方法将当前ByteBuf
的整个数据区映射到一个新的ByteBuf
,并返回这个新的ByteBuf
。这个新的ByteBuf
与原ByteBuf
共享数据区域,但是拥有独立的readerIndex
和writerIndex
。
对新的ByteBuf
数据的修改同样会影响到的原来的ByteBuf
的数据,反之亦然。
2.8 copy方法
copy
方法返回当前ByteBuf
的一个复制品,新的ByteBuf
拥有与原来的ByteBuf
不一样的数据区域,readerIndex
和writerIndex
也是独立的。
同样提供了copy(int index, int length)
方法可以指定复制的数据区域范围。
对新的ByteBuf
数据的修改不会影响到原来的ByteBuf
,反之亦然。
2.9 retain和release方法
ByteBuf
使用引用计数法来表示当前ByteBuf
被引用的次数,如果一个ByteBuf
的被引用次数为0,则释放该ByteBuf
对应的内存。
3 ByteBuf的主要实现及创建
ByteBuf的主要实现类图如下图所示,总体上分为Pooled
和UnPooled
两类,顾名思义为池化的和非池化的,又根据分配的是直接内存还是堆内存分为HeapByteBuf
和DirectByteBuf
。
3.1 通过ByteBufAllocator创建
ByteBufAllocator
有两个实现分别为PooledByteBufAllocator
和UnpooledByteBufAllocator
对应分配出来是的PooledByteBuf
和UnpooledByteBuf
。
PooledByteBufAllocator
将在后续的文章中重点分析,而UnpooledByteBufAllocator
则比较简单,不再赘述。
3.2 通过包裹ByteBuffer及byte[]创建
使用Unpooled.wrappedBuffer
方法可以对jdkButeBuffer
及byte[]
进行包裹创建出一个UnpooledByteBuf
。
4 总结
ByteBuf
主要api有read/write,get/set,slice,duplicate,copy等系列方法。实现类上主要分为Unpooled
和Pooled
,并且支持分配HeapByteBuf
及DirectByteBuf
。
关于作者
王建新,转转架构部服务治理负责人,主要负责服务治理、RPC框架、分布式调用跟踪、监控系统等。爱技术、爱学习,欢迎联系交流。
Netty源码深度解析-ByteBuf(1) ByteBuf简介相关推荐
- Netty 源码深度解析(九) - 编码
概述 一个问题 转载于:https://juejin.im/post/5bff467fe51d4555ed5a3111
- Netty源码分析第5章(ByteBuf)----第5节: directArena分配缓冲区概述
Netty源码分析第5章(ByteBuf)---->第5节: directArena分配缓冲区概述 Netty源码分析第五章: ByteBuf 第五节: directArena分配缓冲区概述 上 ...
- Go netpoll I/O 多路复用构建原生网络模型之源码深度解析
原文 Go netpoll I/O 多路复用构建原生网络模型之源码深度解析 导言 Go 基于 I/O multiplexing 和 goroutine 构建了一个简洁而高性能的原生网络模型(基于 Go ...
- dubbo源码深度解析_Spring源码深度解析:手把手教你搭建Spring开发环境
Spring环境搭建流程,如果是第一次接触spring源码的环境搭建,确实还是比较麻烦的. 作者使用的编译器为目前流行的lntelliJ IDEA,版本为2018旗舰版.Eclipse用户还需要自己揣 ...
- 《Spring源码深度解析》 PDF
Spring源码深度解析 PDF 下载 下载地址:https://pan.baidu.com/s/1o9qEwXW 密码:vwyo 转载:http://download.csdn.net/detail ...
- Java LockSupport以及park、unpark方法源码深度解析
介绍了JUC中的LockSupport阻塞工具以及park.unpark方法的底层原理,从Java层面深入至JVM层面. 文章目录 1 LockSupport的概述 2 LockSupport的特征和 ...
- Spring源码深度解析(郝佳)-学习-源码解析-基于注解bean定义(一)
我们在之前的博客 Spring源码深度解析(郝佳)-学习-ASM 类字节码解析 简单的对字节码结构进行了分析,今天我们站在前面的基础上对Spring中类注解的读取,并创建BeanDefinition做 ...
- 《Spring源码深度解析 郝佳 第2版》AOP
往期博客 <Spring源码深度解析 郝佳 第2版>容器的基本实现与XML文件的加载 <Spring源码深度解析 郝佳 第2版>XML标签的解析 <Spring源码深度解 ...
- 《Spring源码深度解析 郝佳 第2版》ApplicationContext
往期博客: <Spring源码深度解析 郝佳 第2版>容器的基本实现与XML文件的加载 <Spring源码深度解析 郝佳 第2版>XML标签的解析 <Spring源码深度 ...
最新文章
- OpenGL ES 3.0 基础知识
- Kafka设计解析(四):Kafka Consumer解析--转
- [转]软件测试演义——中高级系列(序)
- PHP数组的访问方法有几种,数组常用方法有哪些
- 25. 合并两个排序的链表
- GHOST系统锁定主页常用软件及解决方案
- Spark中repartition和coalesce的区别与使用场景解析
- spring源码之bean加载(bean解析下篇)
- testng数据驱动_TestNG数据提供者
- Java 2 实用教程 第一章 Java入门
- 2022年中国研究生数学建模竞赛
- switchhost
- Matlab的卷积编码实现
- 关于 VB.NET 中 Obsolete 特性的问题
- 单片机c语言*乘法,单片机c语言教程:运算符和表达式(位运算符)
- AR技术应用 の 如何做一个Pokemon GO丢出精灵球抓住皮卡丘吧!(2)
- 生产计划管理软件功能是什么?对生产管理有何好处?
- 广东省如何办理甲级测绘资质
- 各行业分析研究报告 入口汇总
- 美团Java后台一面
热门文章
- 新手必看——Python代码运行的方法都在这里了
- https原理的来龙去脉
- feign 序列化_Spring Feign 序列化机制
- 如何实现集成GB28181监控平台LiveGBS的录像回放时间轴页面
- 统计工作总结——统计图统计表区别
- Praat脚本-008 | 提取某一层时长
- 复制(部分复制,完全复制) Mat对象
- OpenProcessToken LookupPrivilegeValue 和AdjustTokenPrivilege
- tomcat设置https端口时,8443和443的区别
- projectwbs表_Microsoft Project制作WBS基本使用