Netty源码分析(五)—ByteBuf源码分析

本文深入分析Netty的ByteBuf,对比ByteBuffer的局限性,探讨ByteBuf如何实现动态扩容及内存池技术,提高性能。内容包括ByteBuf的结构、功能、AbstractByteBuf的读写操作、内存池实现PooledByteBuf等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Netty源码分析(五)—ByteBuf源码分析

在进行数据传输时往往需要使用缓冲区,Java NIO中使用Buffer作为缓冲区;七种基本数据类型都有自己的缓冲区实现,最常使用的是ByteBuffer,但是ByteBuffer也有局限性;

Netty实现了缓冲区的池化技术,在一定程度上减少了频繁内存分配和GC带来的性能损耗

个人主页:tuzhenyu’s page
原文地址:Netty源码分析(五)—ByteBuf源码分析

(0) ByteBuffer和ByteBuffer

  • ByteBuffer的缺点

    • ByteBuffer长度固定,通过ByteBuffer.allocate()方法或者ByteBuffer.wrap()方法分配后容量不能动态的扩展和收缩;

    • ByteBuffer只有一个标识位置的指针position,读写数据时候需要调用flip()方法或者rewind()方法调整指针位置;

    • ByteBuffer的API功能有限,一些高级和实用的性能不支持

  • ByteBuf的优点

    • 每次写入数据会判断容量是否足够,如果不够则重新创建缓冲区并进行数据复制,实现缓冲区的容量大小可以随着需求动态改变

    • 使用读指针和写指针代替position指针,实现在读写模式之间切换不需要调用ByteBuffer的flip()方法

    • 从内存分配来看,ByteBuf分为堆内存和直接内存两类UnpooledHeapByteBuf和UnpooledDirectByteBuf,上层使用相同的封装;

    • 从内存使用上分为基于对象池的ByteBuf和普通的ByteBuf,基于对象池的ByteBu会重用池中的ByteBuf对象,提高内存的实用率,避免由高负载导致的频繁的触发GC;

(1) ByteBuffer的继承结构

  • ByteBuf是Netty缓存区的顶层抽象类,定义了缓存区操作的所有API;

    • ByteBuf的直接间接实现类有AbstractByteBuf和AbstractReferenceCountedByteBuf,在这两个类中实现了一些公共功能的函数,AbstractReferenceCountedByteBuf按照内存实用情况分为基于内存池的PooledByteBuf和普通的UnPooledHeapByteBufer等;

    • 普通的不基于内存池的缓冲区按照内存分配情况分为UnPooledHeapByteBuf堆缓存区,UnPooledDirectByteBuf直接缓存区和UnPooledUnsafeDirectByteBuf等

    • 基于内存池的缓冲区PooledByteBuf根据内存分配的情况分为PooledDirectByteBuf,PooledHeapByteBuf和PooledUnsafeDirectByteBuf等;

这里写图片描述

(2) ByteBuf的功能

  • 顺序读操作(ByteBuf.readXxx()),类似于ByteBuffer的get()方法

int readInt();    //从readerIndex开始读取4个字节转换成整型数值返回,将readerIndex值增加4

long readLong();    //从readerIndex开始读取8个字节转换成长整型数值返回,将readerIndex值增加8

ByteBuf readBytes(byte[] bytes)    //从readerIndex开始读取bytes.length长度的字节数,并封装成ByteBuf类型返回
  • 顺序写操作(ByteBuf.writeXxx()),类似于ByteBuffer的put()方法

ByteBuf writeInt(int value)    //将参数写入到当前ByteBuf中,操作成功后writeIndex+=4

ByteBuf writeLong(long value)    //将参数写入到当前ByteBuf,操作成功后writeIndex+=8

ByteBuf writeBytes(byte[] bytes)    //将字节数组写入到当前的ByteBuf中,操作成功后writeIndex+=bytes.length
  • 随机读操作(ByteBuf.getXxx())

int getInt(int index)    //从index索引处读取4个字节转换成整型数值返回

long getLong(int index)    //从index索引处读取8个字节转换成整型数值返回

ByteBuf getBytes(int index,byte[] bytes)    //从index索引处读取bytes.length个字节封装成ByteBuf返回;
  • 随机写操作(ByteBuf.setXxx())

ByteBuf setInt(int index,int value)    //将value写入到从readerIndex开始的4个字节中

ByteBuf setLong(int index,long value)    //将value写入到从readerIndex开始的8个字节中;

ByteBuf setBytes(int index,byte[] bytes)    //将bytes字节数组写入到从readerIndex开始的bytes.length长度的字节中;
  • 复制操作(duplicate和copy)

Bytebuf byteBuf.duplicate()    //返回一个复制的ByteBuf对象,该对象和被复制的ByteBuf共享一块缓冲区内存,只是维护着自己独立的读写索引,修改一个另外一个也会变化;

ByteBuf byteBuf.copy()    //复制一个新的ByteBuf对象,内容和索引都是独立的不会相互影响;
  • 查找操作(indexOf和bytesBefore)

int indexOf(int fromIndex,int toIndex,byte value)    //从当前ByteBuf对象中查找value首次出现的位置,查找起始索引是fromIndex,终点索引是toIndex,如果没查找到则返回-1;

int bytesBefore(byte value)    //从当前ByteBuf对象中查找value首次出现的位置,查找起始索引是readerIndex,终点索引是writerIndex,如果没查找到则返回-1;

(3) AbstractByteBuf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值