Netty ByteBuf源码分析
Netty的ByteBuf是JDK中ByteBuffer的升级版,提供了NIO buffer和byte数组的抽象视图。
ByteBuf的主要类集成关系:
(图片来自Netty权威指南,图中有一个画错的地方是PooledByteBuf中的最后一个子类应该是PooledUnsafeDirectByteBuf)
从继承关系可以看出AbstractReferenceCountedByteBuf的子类分为两类:Pooled和Unpooled的ByteBuf。
Pooled ByteBuf是基于对象池的ByteBuf(会被缓存),Unpooled则是普通的ByteBuf对象。
无论是否基于内存池的ByteBuf,它的子类有分为DirectByteBuf和HeapByteBuf分别表示在堆外内存分配的缓冲区和在堆内存的缓冲区。
堆内存缓冲区的特点是分配和回收速度快,可以被JVM自动回收;缺点是如果进行Socket的IO读写,需要额外做一次内存复制。
堆外内存的缓冲区相对于堆内存的缓冲区,分配和回收的速度会慢一些,但是将它写入或从Socket Channel读取数据是,会少一次内存复制,速度比堆内存更快一些。
BufferBuf也提供了一类API来将自己转化成为ByteBuffer以便于在需要ByteBuffer的地方进行操作。
AbstractByteBuf
AbstractByteBuf定义了ByteBuf的基础属性和一些公用的方法。
主要成员变量有:
readerIndex
writerIndex
markedReaderIndex
markedWriterIndex
maxCapacity
可以看到ByteBuf中分别定义了读写游标,也就是说读游标和写游标是分离的,这相对于ByteBuffer只使用一个position,在读写操作时会便利很多。
一块缓冲区会被两个游标分隔为三块区域,分别是已经读取过的、可读的、剩余可写的。
在写入数据后可以直接开始读取,不需要flip操作。
另外AbstractByteBuf中的方法分为三类:
读取数据、写入数据、操作游标
读取操作分为readXXX和getXXX,以读取Long为例,
readLong()方法在当前readerIndex位置读取8个Byte并增加readerindex的值;
getLong(int index)则需要接收一个index参数,从index位置开始读取8个Byte,get操作不会改变readerIndex的值。
写入操作也有两类,分别是setXXX和writeXXX,
writeLong(long value)方法在当前writerIndex位置开始写入一个Long值并增加writerIndex的值;
setLong(int index, long value)方法则接收一个index参数作为写入的位置,写入操作不修改writerIndex的值。
索引操作就是通过setReaderIndex之类的方法改变readerIndex的值来重新读取数据,非常简单,不做说明。
AbstractReferenceCountedByteBuf
从类名上看,AbstractReferenceCountedByteBuf主要是实现了对引用的计数,类似于JVM内存回收的对象引用计数器,用于跟踪对象的分配和销毁。
只有一个成员变量:refCnt,看命名也知道是用于计数的,并且用AtomicIntegerFieldUpdater来实现线程安全的计数。
retain API用于增加引用的计数。
release则用于减少计数值。
定义deallocate方法让子类去实现当引用计数为0时的操作(由子类实现具体的“回收”操作)。
UnpooledHeapByteBuffer
UnpooledHeapByteBuffer是不适用对象池,且直接在堆内存上分配的缓冲区。
ByteBufAllocator alloc:创建了这个缓冲区的分配器
byte[] array:底层存储
ByteBuffer tmpNioBuf:Nio ByteBuffer对象,用于将自身转换成一个ByteBuffer对象
构造方法非常简单:
记录分配器alloc;
初始化数组;
将读写位置调整为0;
这个构造方法则是传入byte数组做初始化,writerIndex调整到数组后的第一个位置。
两个构造方法都有maxCapacity参数,且初始容量要么是initialCapacity要么是initalArray的长度,说明缓冲区的大小是可以调整的,最大不超过maxCapacity。
通过capacity来调整缓冲区的大小。如果newCapacity小于当前array的length,那么会有部分数据被丢弃。如果newCapacity超过array的length,那么新扩容的位置数据未空。
UnpooledDirectByteBuf
ByteBufAllocator alloc:使用的分配器
ByteBuffer buffer:内部用于存储数据的结构
ByteBuffer tmpNioBuf:临时的ByteBuffer,在将自己转换成ByteBuffer对象时会使用
int capacity:容量
doNotFree:标志ByteBuffer是否可以回收
区别于UnpooledHeapByteBuf,UnpooledDirectByteBuf的扩容操作不在是申请数组进行数据拷贝,而是申请新的ByteBuffer之后进行收拷贝,而ByteBuffer一定是Direct的。
deallocate实现了底层存储ByteBuffer的回收操作,即在引用计数为0时将DirectByteBuffer回收掉(DirectByteBuffer的内存是由自己回收的,而不是JVM)。
UnpooledUnsafeDirectByteBuf
UnpooledUnsafeDirectByteBuf和UnpooledUnsafeDirectByteBuf的区别在于UnpooledUnsafeDirectByteBuf直接使用ByteBuffer来操作数据,而UnpooledUnsafeDirectByteBuf采用Unsafe来操作数据。
UnpooledUnsafeDirectByteBuf的_getLong实现:
UnpooledUnsafeDirectByteBuf的_getLong实现:
AbstractReferenceCountedByteBuf子类的另一个分支是PooledByteBuf,即使用对象池,会被缓存的ByteBuffer。
PooledByteBuf有三个子类:
PooledHeapByteBuf
PooledDirectByteBuf
PooledUnsafeDirectByteBuf
他们分别和Unpooled的几个子类对应。
对于Pooled的实现,详见Netty对象池实现分析。
欢迎关注我的个人公众号,会写一些列关于消息中间件的文章,也欢迎交流任何技术问题,或者扯扯淡。
Netty ByteBuf源码分析的更多相关文章
- Netty学习篇⑥--ByteBuf源码分析
什么是ByteBuf? ByteBuf在Netty中充当着非常重要的角色:它是在数据传输中负责装载字节数据的一个容器;其内部结构和数组类似,初始化默认长度为256,默认最大长度为Integer.MAX ...
- netty : NioEventLoopGroup 源码分析
NioEventLoopGroup 源码分析 1. 在阅读源码时做了一定的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限.为了方便 IDE 查看.跟踪.调试 代码,所以在 github ...
- netty UnpooledHeapByteBuf 源码分析
UnpooledHeapByteBuf 是基于堆内存进行内存分配的字节缓冲区,没有基于对象池技术实现,这意味着每次I/O的读写都会创建一个新的UnpooledHeapByteBuf,频繁进行大块内存的 ...
- 【Netty】源码分析目录
前言 为方便系统的学习Netty,特整理文章目录如下. [Netty]第一个Netty应用 [Netty]Netty核心组件介绍 [Netty]Netty传输 [Netty]Netty之ByteBuf ...
- netty(六) buffer 源码分析
问题 : netty的 ByteBuff 和传统的ByteBuff的区别是什么? HeapByteBuf 和 DirectByteBuf 的区别 ? HeapByteBuf : 使用堆内存,缺点 ,s ...
- NIO-EPollSelectorIpml源码分析
目录 NIO-EPollSelectorIpml源码分析 目录 前言 初始化EPollSelectorProvider 创建EPollSelectorImpl EPollSelectorImpl结构 ...
- Netty源码分析第5章(ByteBuf)---->第1节: AbstractByteBuf
Netty源码分析第五章: ByteBuf 概述: 熟悉Nio的小伙伴应该对jdk底层byteBuffer不会陌生, 也就是字节缓冲区, 主要用于对网络底层io进行读写, 当channel中有数据时, ...
- Netty源码分析第5章(ByteBuf)---->第2节: ByteBuf的分类
Netty源码分析第五章: ByteBuf 第二节: ByteBuf的分类 上一小节简单介绍了AbstractByteBuf这个抽象类, 这一小节对其子类的分类做一个简单的介绍 ByteBuf根据不同 ...
- Netty源码分析第5章(ByteBuf)---->第3节: 缓冲区分配器
Netty源码分析第五章: ByteBuf 第三节: 缓冲区分配器 缓冲区分配器, 顾明思议就是分配缓冲区的工具, 在netty中, 缓冲区分配器的顶级抽象是接口ByteBufAllocator, 里 ...
随机推荐
- 由12306.cn谈谈网站性能技术
12306.cn网站挂了,被全国人民骂了.我这两天也在思考这个事,我想以这个事来粗略地和大家讨论一下网站性能的问题.因为仓促,而且完全基于本人有 限的经验和了解,所以,如果有什么问题还请大家一起讨论和 ...
- 多媒体开发库 之 SDL 详解
SDL 简介 SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成.SDL提供了数种控制图像.声音.输出入的函数,让开发者只要用相同或是相似的 ...
- SQL Server 中函数的理解总结
T-SQL语言为我们提供了更加灵活的方式操作数据,那就是函数,函数总的分为三大类:标量函数:(传入一个参数,再传出一个参数)聚合函数(传入多个参数,传出一个参数),表值函数(传入一个结果集对象,让我们 ...
- 论如何把JS踩在脚下 —— JQuery基础及Ajax请求详解
一.什么是JQuery? JQuery是一种JavaScript框架,是一堆大神搞出来的能够让前端程序猿敲更少代码.实现更多功能的工具(在此,跪谢各位JQuery开发大大们!!!).JQuery的使用 ...
- 生成JSON数据--fastjson(阿里)方法
fastjson(阿里)方法生成JSON数据: 与Gson类似,创建相应类,再使用JSON.toJSONString()添加对象 要求:生成如下JSON数据 1.{"age":3, ...
- Activiti工作流几种驳回方式的实现与比较
最近公司做的一个项目要实现工作流程的收回,驳回等操作,而采用的工作流引擎并不支持驳回功能,这个项目恰好就我和一个实习生一块做,所以这个问题就落到我的头上来解决了... 客户提出的要求是驳回时要记录日志 ...
- [Leetcode] Binary search -- 475. Heaters
Winter is coming! Your first job during the contest is to design a standard heater with fixed warm r ...
- A comparison of local caches (2) 【本地缓存之比较 (2)】
接上一篇: A comparison of local caches (1) [本地缓存之比较 (1)] This article will compare the asynchronous loca ...
- 《Python编程从入门到实践》第三章_列表简介
什么是列表呢? 官方说明就是由一些列按特点顺序排列的元素组成.其实可以看出很多个字符串的有序组合吧,里面的内容可以随时的删除,增加,修改. 下面这个就是一个列表,python打印列表的时候会将中括号和 ...
- php实现获取汉字的首字母
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...