netty源码浅析-byteBuf介绍

Netty源码分析(五)—ByteBuf源码分析 Netty源码分析(五)—ByteBuf源码分析 在进行数据传输时往往需要使用缓冲区,Java NIO中使用Buffer作为缓冲区;七种基本数据类型都有自己的缓冲区实现,最常使用的是ByteBuffer,但是ByteBuffer也有局限性; Netty实现了缓冲区的池化技术,在一定程度上减少了频繁内存分配和GC带来的性能损耗 个人主页:tuzhenyu’s page 阅读详情

byteBuf

byteBuf介绍

在介绍netty的byteBuf之前我们先来回顾一下nio的byteBuffer,byteBuffer内部维护了一个byte[]数组,而且提供了几个属性position、limit、capacity、mark四个属性来组织byteBuffer。

  • position:当前操作的位置
  • limit:最大可以读或者可写的位置
  • capacity:最大的空间容量是多少,byteBuffer在创建时,就固定下来
  • mark:标记当前的位置,下次可以回到这个位置
ByteBuffer byteBuffer = ByteBuffer.allocate(128);
        byteBuffer.putInt(1);
        byteBuffer.putInt(2);
        byteBuffer.flip();
        byteBuffer.getInt(1);

当我们需要读取数据时需要执行flip操作完成模式的切换,将写入模式变为读取模式,其实就是将position的值赋值给limit,然后将position赋值为0就可以从position的位置开始到limit位置结束读取。在进行读写时频繁的执行flip操作进行指针的移动时可能或出现错误,并且byteBuffer在内存分配后不能改变,当读写内容大于缓存区大小的时候会发生越界异常。

netty的byteBuf是对byteBuffer的优化,同样用于网络IO的读写,使用起来比较简单,byteBuf维护了两个指针一个读指针和一个些指针,两个指针相互独立,互不影响,在写入数据的时候,只会移动写指针,当去读数据时只会移动读取指针,并且操作过程中会对读指针进行判断不能超过写指针,同时写指针如果超过了缓冲区大小,如果不够将进行扩容,我们来看下byteBuf的结构

<pre>
 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      |                   |     (CONTENT)    |                  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 * </pre>

当读取数据时会移动读指针,当写数据时会移动写指针,而从0-readerIndex的长度就是已经读取过的长度,从readerIndex-writerIndex就是可以读取的长度,从writerIndex-capacity就是可以写入的长度,当写入不够的时候会进行扩容。
我们看下AbstractByteBuf的属性

int readerIndex;//读指针
int writerIndex;//写指针
private int markedReaderIndex;//记录读指针
private int markedWriterIndex;//记录写指针
private int maxCapacity;//最大容量
基本API介绍

byteBuf提供了很多方法由子类来实现,我们这里先举几个简单的例子
随机获取:

方法说明
getInt(int index)返回当前索引的整型
getByte(int index)返回当前索引的字节
getBytes(int index, ByteBuf dst)从索引位置获取字节到dst中

随机写入:

方法说明
setByte(int index, int value)在指定的索引位置设置 byte 值
setInt(int index, int value)在指定索引位置设置int值
setBytes(int index, ByteBuf src)在指定索引位置设置src

顺序读:

方法说明
readInt()从读索引位置读取int值
readBytes(int length)从读取索引位置读取length长数据
readBoolean()读取一个布尔值,读索引+1
顺序写:
方法说明
––
writeInt(int value)从写入索引位置写入int值
writeBytes(ByteBuf src)从写入索引位置写入src
writeBoolean(boolean value)从写入索引位置写入布尔值

副本:

方法说明
duplicate()从写入索引位置写入int值
slice()从写入索引位置写入src
asReadOnly()从写入索引位置写入布尔值
copy()复制一个byteBuf
copy(int index, int length)有数据独立副本

顺序写:

方法说明
ByteBuffer nioBuffer()转变为ByteBuffer
ByteBuffer[] nioBuffers()转变为ByteBuffer数组

byteBuf方法还有很多我们这里只是简单列举了一些,更多的方法可以自己到官网查看。

byteBuf分类

byteBuf有很多种分类,下面我们来看看

  • 第一种:基于堆内存和直接内存划分

堆内存分配的byteBuf类名中会包含heap单词,比如PooledHeapByteBuf。堆内存分配是指分配的内存是在jvm内分配的,也就是会被jvm管理,存在垃圾回收

直接内存分配,类名中会包含direct单词,比如PooledDirectByteBuf,直接内存是指在jvm外申请的内存,他在垃圾回收机制作用范围之外,只有当指向直接内存的对象被回收时,堆外内存才会被回收,而堆外内存一般使用时间比较长,堆内的对象GC年龄达到了-XX:MaxTenuringThreshold的Young GC后就会进入老年代,而这些对象很小,但堆外申请的内存可能很大,当触发full GC的时候才会被清理掉,这样可能会导致堆外内存很难被回收。这里要考虑手动回收 ,通过执行Cleaner的clean方法清理掉堆外内存,执行unsafe的freeMemory方法。

  • 第二种:基于池化和非池化

池化是指netty是会一次性申请一块默认16M大小的内存,然后根据申请内存的大小分为tiny、small、normal去申请一块连续的内存封装成byteBuf。类名中包含pooled单词,有关池化内存如果分配我们下面在做介绍。

非池化就是直接调用系统API进行实现,类名中包含unPooled单词

  • 第三种:safe和unsafe

这里的safe和unsafe其实是指jdk中有一个unsafe类,同过unsafe类可以直接拿到内存地址,直接通过内存地址进行读写,这个是jdk底层的方法不对外进行暴露,都是一些native方法,只是提供了实现方法的定义和约束,真正的实现是通过C或者C++语言实现,用户使用这些api可能会有不安全的行为,所以这里代表是不安全的。这类byteBuf类名中会包含unsafe单词。

safe相反就是不能拿到jvm的具体内存进行操作,这里代表安全。这类byteBuf类名中会有safe单词。

byteBuf分配器

byteBuf分配器主要是用来分配byteBuf的工具类,他的顶级抽象是ByteBufAllocator接口,接口中定义了很多有关byteBuf的操作方法,该接口实现抽象类是AbstractByteBufAllocator类,他实现了接口的大部分功能,定义了分配byteBuf的骨架逻辑,其他实现交给子类具体实现

/**
 * Skeletal {@link ByteBufAllocator} implementation to extend.
 */
public abstract class AbstractByteBufAllocator implements ByteBufAllocator

这个抽象类有两个实现类PooledByteBufAllocator和UnpooledByteBufAllocator,通过类名我们应该可以看得出这两个类一个是用来创建池化byteBuf的和非池化byteBuf的,具体的实现由子类重写。我们先来看看其中的几个方法

public ByteBuf buffer() {
     //判断默认是不是申请直接内存
        if (directByDefault) {
            return directBuffer();
        }
        return heapBuffer();
    }

 public ByteBuf heapBuffer() {
     //256 MAX_VALUE 
        return heapBuffer(DEFAULT_INITIAL_CAPACITY, DEFAULT_MAX_CAPACITY);
    }

public ByteBuf heapBuffer(int initialCapacity, int maxCapacity) {
        //如果长度为0返回空的byteBuf
        if (initialCapacity == 0 && maxCapacity == 0) {
            return emptyBuf;
        }
        //验证传入的长度和最大容量
        validate(initialCapacity, maxCapacity);
        return newHeapBuffer(initialCapacity, maxCapacity);
    }

protected abstract ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity);

这里可以看到,我们在没有传入申请内存块大小的时候,默认是申请256大小的byte,并且会判断是申请直接内存还是堆内存,最终实现由子类实现。

第五天 Labview数据记录(5.4 EXCEL文件读写) Excel 文件读写在数据处理、自动化办公、数据分析等领域具有重要的意义。以下是 Excel 文件读写的主要应用场景和意义:1. 数据管理和整理;2. 自动化办公;3. 数据分析和可视化;4. 系统集成;5. 报表生成;6. 教育和培训;7. 实际应用场景。Excel 文件读写的意义在于提高数据处理的效率、减少人工操作、支持自动化办公、促进数据分析和可视化,以及实现系统之间的数据交互。无论是企业、组织还是个人,都可以通过 Excel 文件读写实现数据的高效管理和利用。 阅读详情

相关推荐

MATLAB实战:5步搞定铣削稳定性叶瓣图(附完整代码解析)

本文提供了一份基于MATLAB的铣削稳定性叶瓣图实战指南。通过5个清晰步骤,从动力学原理出发,详细解析了利用半离散法构建稳定性判据、模块化代码设计、高效参数扫描及高级可视化的完整流程,并附有完整代码,帮助工程师快速预测和规避加工颤振,优化铣削工艺参数。

weixin_29197051的博客 193

netty 重要原理分享

回顾linux网络IO 遗留问题 Netty特点 异步非阻塞通信 零拷贝 内存池 总结 内存分配流程 内存释放 个人看法 高效的 Reactor 线程模型 无锁化的串行设计理念 高效的并发编程 高性能的序列化框架 灵活的 TCP 参数配置能力 回顾linux网络IO 遗留问题 epoll 支持两种事件触发模式,分别是边缘触发(edge-triggered,ET)和水平触发(level-triggered,LT).

王温暖的博客 984

CCD 技术介绍(基于innovus引擎CCOpt)

CCD:全称是,并行优化clock和data path。CCOpt:全称是Clock的timing分为两种模式,和。preCTS并没有clock,因此需要建立一个,从clock端口到寄存器CK端的来自sdc中的设置;postCTSupdateIO latency,clock就会自动的转换成propagatedclock,这时就是实际时钟互连线网络的delay。在实际设计中,clock起始于ideal。

m0_61003348的博客 8973

Netty的只读ByteBuf

Netty的只读ByteBuf

听海边涛声 187

【重磅干货】介质损耗因数(tanδ)揭秘:如何精准定位材料劣化最严重的温度?附权威研究PDF!

是评估绝缘材料性能的核心指标,能直接反映材料内部能量损耗和微观结构变化。通过分析tanδ-温度曲线的峰值点,可精准定位材料劣化最严重的温度。:极化损耗峰值的温度点(如环氧树脂的80℃)是材料性能拐点,需重点关注!:图3对比了5种材料的tanδ-温度曲线,峰值温度差异高达50℃!在电力设备、电子元器件等领域,材料的老化与温度密切相关。:[《介质损耗峰值温度在设备寿命预测中的应用》]在不同温度下测量tanδ,绘制曲线图。:[《多材料介质损耗峰值温度对比研究》]:基于tanδ峰值温度开发的。

mubiao05的博客 1348

RDMA性能调优实战:如何用ib_*命令榨干你的Mellanox网卡带宽?

本文深入探讨了如何利用ib_*命令工具集对RDMA网络进行深度性能调优,以充分释放Mellanox网卡的带宽潜力。文章从理解Send/Write/Read三种核心通信原语的差异入手,逐步指导读者通过调整消息大小、队列深度、内联数据等关键参数,并结合系统级的NUMA绑定、中断亲和性等优化策略,实现从基准测试到逼近硬件极限的性能提升。

weixin_29306011的博客 86

ByteBuff常用方法,使用

ByteBuff常用方法,使用

一点光辉的博客 1万+

手把手教你用Wireshark抓包分析BLE广播包:从PDU结构到AD Type实战解析

本文详细介绍了如何使用Wireshark工具抓取并分析BLE广播包,从PDU结构到AD Type的实战解析。通过硬件设备选择、软件配置、协议栈解析及高级故障排查,帮助开发者深入理解蓝牙低功耗通信机制,提升物联网设备调试效率。

weixin_30482383的博客 417

吃透Netty源码系列二十三之池化内存分配四

吃透Netty源码系列二十三之池化内存分配四PoolSubpage的allocategetNextAvailfindNextAvailfindNextAvail0removeFromPooltoHandle重点以及为什么要加上0x4000000000000000L PoolSubpage的allocate 继续上一篇的,现在执行到subpage.allocate(),里面才是对子页可分配的内存做了...

王伟王胖胖的博客 1305

SRAM vs RRAM:存算一体芯片选型指南(含最新技术对比)

本文深入对比了SRAM与RRAM在存算一体芯片设计中的核心差异,为硬件工程师和架构师提供实战选型指南。文章从技术本质、性能、功耗、成本及设计风险等多维度剖析,指出SRAM基于成熟CMOS工艺,适合高精度、低延迟场景;而RRAM凭借非易失性和高密度潜力,在超低功耗、固定模型应用中优势明显。决策需综合项目预算、上市时间及技术储备。

e4f5g6h的博客 937

【论文复现】——基于改进FPFH特征提取的点云模板匹配方法

基于改进FPFH特征提取的点云模板匹配方法 [J]. 应用激光, 2024, 44 (04): 196-204.

点云侠的博客 611

netty5学习笔记-内存池1-PoolChunk

从netty 4开始,netty加入了内存池管理,采用内存池管理比普通的new ByteBuf性能提高了数(2)十倍。相信有些朋友会和我一样,对他的实现方式很感兴趣。这里把学习netty内存池的过程记录下来,与大家一起分享。 首先给大家介绍的是PoolChunk, 该类主要负责内存块的分配与回收,下面看看几个重要的术语: page: 可以分配的最小的内存块单位。 chunk: chunk是一

youaremoon的专栏 8354

基于Simulink的自适应控制(Adaptive Control)电励磁同步电动机

目录基于Simulink的自适应控制(Adaptive Control)电励磁同步电动机项目实例1. 项目背景2. 系统架构2.1 电励磁同步电动机模型2.2 三相逆变器模型2.3 自适应控制器(Adaptive Controller)2.4 系统框图3. 模型设计3.1 创建Simulink模型3.2 自适应控制(Adaptive Control)设计3.3 仿真环境搭建4. 参数优化4.1 自动调优5. 实际应用案例5.1 工业驱动系统5.2 风力发电系统6. 结论进一步优化建议需求分析电励磁同步电动机

MHD0815的博客 266

【Netty4】netty ByteBuf (一)如何创建ByteBuf对象

有一点我们需要知道的是,ByteBuf的jar包,是可以单独使用的。比如某个项目中有一个场景,需要处理某个自定义的协议,那么我们在解析协议时,就可以将接收到的将字节内容写入一个ByteBuf,然后从ByteBuf中慢慢的将内容读取出来。下面让我们用一个例子简单的了解下ByteBuf的使用。 ByteBuf的创建 要想使用ByteBuf,首先肯定是要创建一个ByteBuf,更确切的说法就是要申请一块...

m0_45406092的博客 6124

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

netty源码之ByteBuf详解

一、背景简介 ByteBuf,顾名思义,就是字节缓冲区,是Netty中非常重要的一个组件。熟悉jdk NIO的同学应该知道ByteBuffer,正是因为jdk原生ByteBuffer使用比较复杂,某些场景下性能不是太好,netty开发团队重新设计了ByteBuf用以替代原生ByteBuffer。 二、ByteBuf和ByteBuffer对比 下面用图示来展示ByteBuf和ByteBuffer工作原理: ①、ByteBuffer ByteBuffer依靠flip()来切换模式,在读模式下..

bobozai86的博客 9624

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Netty Review - ByteBuf内存池源码解析

ByteBuf 内存池是 Netty 中用于管理 ByteBuf 对象的一种机制,旨在提高内存的使用效率和性能。

小工匠 7392

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Netty源码—ByteBuf原理二

首先从线程对应的PoolThreadCache里获取一个PoolArena,然后从PoolArena的一个ChunkList中取出一个Chunk进行内存分配。接着,在这个Chunk上进行内存分配时,会判断需要分配的内存大小是否大于一个Page的大小。如果需要分配的内存超过一个Page的大小,那么就以Page为单位进行内存分配。如果需要分配的内存远小于一个Page的大小,那么就会找一个Page并把该Page切分成多个SubPage然后再从中选择。

sdgfafg_25的博客 1092

Netty Review - ByteBuf扩容机制源码解析

ByteBuf 扩容机制是指在写入数据时,如果当前容量不足以容纳新增的数据,则需要进行动态扩容,以适应数据量的增长。容量检查在写入数据之前,会先检查当前可写入的容量是否足够。这通常是通过比较写索引和容量之间的关系来实现的。如果当前可写入容量不足,就需要进行扩容操作。内存分配当需要扩容时,会分配一个更大的内存空间来存储数据。这个内存空间的大小通常由扩容策略决定,可以是固定大小的增量,也可以是根据某种规则动态计算的。数据迁移在分配更大的内存空间后,原有的数据需要从旧的内存空间复制到新的内存空间中。

小工匠 7141

Netty ByteBuf 详解及详细源码展示

Netty的ByteBuf优化了Java NIO ByteBuffer的读写分离、动态扩容和内存管理问题,通过独立指针(readerIndex/writerIndex)和池化技术(PooledByteBufAllocator)提升性能。其核心实现包括堆/直接内存分配、零拷贝(slice()/CompositeByteBuf)及泄漏检测机制。源码中,AbstractByteBuf处理基础操作,PooledByteBuf实现内存复用,支持自动扩容(默认翻倍策略)。典型应用如网络编解码和零拷贝

csdn_tom_168的博客 895

Netty 中的 ByteBuf 为什么会发生内存泄漏

该文所涉及的 netty 源码版本为 4.1.6。

黎明就要到来 1996

Netty学习——源码篇1 Netty之Bytebuf

弊端一:网络传输方式存在弊端。传统的RPC框架或者基于RMI等方式的远程服务调用都采用BIO,当客户端的并发压力或网络延时增大的时候,BIO会因频繁“wait”导致I/O线程经常出现阻塞的情况,由于线程本身无法高效的工作,I/O处理能力自然就会下降。下面通过BIO通信模型看一下BIO通信的弊端。

geminigoth的博客 2402

Netty学习——源码篇10 Netty内存分配ByteBuf基础

ByteBuf是Netty整个结构中最为底层的模块,主要负责把数据从底层I/O读取到ByteBuf,然后传递给应用程序,应用程序处理完成后再把数据封装成ByteBuf写回I/O。所以,ByteBuf是直接与底层打交道的一层抽象。

geminigoth的博客 1672

Netty源码—7.ByteBuf原理三

这些固定大小分别有:tiny类型规则的是16B的整数倍直到498B,small类型规则的有512B、1K、2K、4K,normal类型规定的有8K、16K、32K。PoolSubpage中的chunk属性表示该SubPage从属于哪个PoolChunk,PoolSubpage中的elemSize属性表示该SubPage是以多大的数值进行划分的,PoolSubpage中的bitmap属性会用来记录该SubPage的内存分配情况,一个Page里的PoolSubpage会连成双向链表。

mjunz的博客 1109

Netty中的ByteBuf

在FixedLengthFrameDecoder中查看源码decode发现:如果字节满足条件后会返回in.readRetainedSlice(frameLength),这里用了retained,也就是说会把in的引用计数加1,但是在FixedLengthFrameDecoder中却没有发现把引用计数减1的地方。很疑惑为什么能做到内存不泄漏,所以继续查看其他源码。 protected Object

hanlengxingkong的专栏 3000

[netty核心类]--缓冲区ByteBuf

本文主要包括以下内容: 1)ByteBuf的三种类型:heapBuffer(堆缓冲区)、directBuffer(直接缓冲区)以及Composite Buffer(复合缓冲区)。 2)ByteBuf的工作原理。 3)ByteBuf与JDK中ByteBuffer的区别以及对比 4)ByteBuf的引用计数器实现类AbstractReferenceCountedByt

惜暮 3万+

Netty源码—6.ByteBuf原理一

slice()方法会从原始ByteBuf中截取一段,这段数据是从readIndex到writerIndex的,同时返回的新的ByteBuf的最大容量maxCapacity为原始ByteBuf的readableBytes()。答:对于Page级别的内存分配与释放是直接通过完全二叉树的标记来寻找某一个连续内存的。所有类型的ByteBuf最终都是通过Netty里的内存分配器分配出来的,Netty里的内存分配器都有一个最顶层的抽象ByteBufAllocator,用于负责分配所有类型的内存。

mjunz的博客 1092
上一篇: netty源码浅析-数据接入与解码过程
下一篇: 设计模式-01设计原则
胖柯G
博客等级 码龄10年 453粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值