Netty(4)-二进制载体ByteBuf

netty byteBuf readBytes方法的小坑(内存溢出,LEAK问题) netty LEAK readBytes 阅读详情

一.ByteBuf的介绍

在 Netty 中,客户端和服务端之间的通信数据载体为 ByteBuf,即字节块对象。

在这里插入图片描述

如以下程序所示:

/*
     * @Author ARong
     * @Description 接收到服务端消息时触发
     * @Param [ctx, msg]
     * @return void
     **/
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 接收到服务端发送的ByteBuf,进行解析
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println(String.format("服务端读取到数据%s From %s",
                byteBuf.toString(Charset.forName("utf-8")),
                getCurTime()));

        // 构造一个ByteBuf写回给服务端
        ByteBuf byteBuf1 = getByteBuf(ctx);
        ctx.channel().writeAndFlush(byteBuf1);
    }

二.ByteBuf的结构

ByteBuf的结构可分为三块,分别是可废弃字节区域、可读字节区域、可写字节区域:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GUFiyZnL-1580796362091)(http://note.youdao.com/yws/res/9905/4BEE1903F64A4BF491681DD8D3CF6FFA)]

  1. 以上三段内容是被两个指针给划分出来的,从左到右,依次是读指针(readerIndex)、写指针(writerIndex),然后还有一个变量 capacity,表示 ByteBuf 底层内存的总容量
  2. 从 ByteBuf 中每读取一个字节,readerIndex 自增1,ByteBuf 里面总共有 writerIndex-readerIndex 个字节可读, 由此可以推论出当 readerIndex 与 writerIndex 相等的时候,ByteBuf 不可读
  3. 写数据是从 writerIndex 指向的部分开始写,每写一个字节,writerIndex 自增1,直到增到 capacity,这个时候,表示 ByteBuf 已经不可写了
  4. ByteBuf 里面其实还有一个参数 maxCapacity,当向 ByteBuf 写数据的时候,如果容量不足,那么这个时候可以进行扩容,直到 capacity 扩容到 maxCapacity,超过 maxCapacity 就会报错

三.ByteBuf的API

容量相关

  1. capacity()

表示 ByteBuf 底层占用了多少字节的内存(包括丢弃的字节、可读字节、可写字节),不同的底层实现机制有不同的计算方式。

  1. maxCapacity()

表示 ByteBuf 底层最大能够占用多少字节的内存,当向 ByteBuf 中写数据的时候,如果发现容量不足,则进行扩容,直到扩容到 maxCapacity,超过这个数,将抛出异常

  1. readableBytes() 与 isReadable()

readableBytes() 表示 ByteBuf 当前可读的字节数,它的值等于 writerIndex-readerIndex,如果两者相等,则不可读,isReadable() 方法返回 false

  1. writableBytes()、 isWritable() 、maxWritableBytes()

writableBytes() 表示 ByteBuf 当前可写的字节数,它的值等于 capacity-writerIndex,如果两者相等,则表示不可写,isWritable() 返回 false,但是这个时候,并不代表不能往 ByteBuf 中写数据了, 如果发现往 ByteBuf 中写数据写不进去的话,Netty 会自动扩容 ByteBuf,直到扩容到底层的内存大小为 maxCapacity,而 maxWritableBytes() 就表示可写的最大字节数,它的值等于 maxCapacity-writerIndex

读写指针相关的 API

  1. readerIndex() 与 readerIndex(int)

前者表示返回当前的读指针 readerIndex, 后者表示设置读指针

2 .writeIndex() 与 writeIndex(int)

前者表示返回当前的写指针 writerIndex, 后者表示设置写指针

  1. markReaderIndex() 与 resetReaderIndex()

前者表示把当前的读指针保存起来,后者表示把当前的读指针恢复到之前保存的值,下面两段代码是等价的

// 代码片段1
int readerIndex = buffer.readerIndex();
// .. 其他操作
buffer.readerIndex(readerIndex);


// 代码片段二
buffer.markReaderIndex();
// .. 其他操作
buffer.resetReaderIndex();

推荐使用代码片段二这种方式,不需要自己定义变量,无论 buffer 当作参数传递到哪里,调用 resetReaderIndex() 都可以恢复到之前的状态,在解析自定义协议的数据包的时候非常常见,推荐大家使用这一对 API

  1. markWriterIndex() 与 resetWriterIndex()

这一对 API 的作用与上述一对 API 类似,这里不再 赘述

读写 API

本质上,关于 ByteBuf 的读写都可以看作从指针开始的地方开始读写数据

  1. writeBytes(byte[] src) 、 buffer.readBytes(byte[] dst)

writeBytes() 表示把字节数组 src 里面的数据全部写到 ByteBuf,而 readBytes() 指的是把 ByteBuf 里面的数据全部读取到 dst,这里 dst 字节数组的大小通常等于 readableBytes(),而 src 字节数组大小的长度通常小于等于 writableBytes()

  1. writeByte(byte b) 、 buffer.readByte()

writeByte() 表示往 ByteBuf 中写一个字节,而 buffer.readByte() 表示从 ByteBuf 中读取一个字节,类似的 API 还有 writeBoolean()、writeChar()、writeShort()、writeInt()、writeLong()、writeFloat()、writeDouble() 与 readBoolean()、readChar()、readShort()、readInt()、readLong()、readFloat()、readDouble()

与读写 API 类似的 API 还有 getBytes、getByte() 与 setBytes()、setByte() 系列,唯一的区别就是 get/set 不会改变读写指针,而 read/write 会改变读写指针,这点在解析数据的时候千万要注意

  1. release() 与 retain()

由于 Netty 使用了堆外内存,而堆外内存是不被 jvm 直接管理的,也就是说申请到的内存无法被垃圾回收器直接回收,所以需要我们手动回收。有点类似于c语言里面,申请到的内存必须手工释放,否则会造成内存泄漏。

Netty 的 ByteBuf 是通过引用计数的方式管理的,如果一个 ByteBuf 没有地方被引用到,需要回收底层内存。默认情况下,当创建完一个 ByteBuf,它的引用为1,然后每次调用 retain() 方法, 它的引用就加一, release() 方法原理是将引用计数减一,减完之后如果发现引用计数为0,则直接回收 ByteBuf 底层的内存。

  1. slice()、duplicate()、copy()

这三个方法通常情况会放到一起比较,这三者的返回值都是一个新的 ByteBuf 对象

  1. slice() 方法从原始 ByteBuf 中截取一段,这段数据是从 readerIndex 到 writeIndex 之间的可读区域,同时,返回的新的 ByteBuf 的最大容量 maxCapacity 为原始 ByteBuf 的 readableBytes()
  2. duplicate() 方法把整个 ByteBuf 都截取出来,包括所有的数据区域(包括废弃区域和可用区域),指针信息。
    slice和duplicate方法不会拷贝数据,它们只是通过改变读写指针来改变读写的行为「浅拷贝」。
  3. copy() 会直接从原始的 ByteBuf 中拷贝所有的信息,包括读写指针以及底层对应的数据,因此,往 copy() 返回的 ByteBuf 中写数据不会影响到原始的 ByteBuf「深拷贝」。

TIPS:

slice() 和 duplicate() 不会改变 ByteBuf 的引用计数,所以原始的 ByteBuf 调用 release() 之后发现引用计数为零,就开始释放内存,调用这两个方法返回的 ByteBuf 也会被释放,这个时候如果再对它们进行读写,就会报错。

// retainedSlice 等价于
slice().retain();

// retainedDuplicate() 等价于
duplicate().retain()
netty之微信-数据传输载体 ByteBuf (八) 数据传输载体 ByteBuf 介绍 在前面一小节,我们已经了解到 Netty 里面数据读写是以 ByteBuf 为单位进行交互的,这一小节,我们就来详细剖析一下 ByteBuf ByteBuf结构 首先,我们先来了解一下 ByteBuf 的结构       以上就是一个 ByteBuf 的结构图,从上面这幅图可以看到 ByteBuf 是一个字节容器,容器里面的的数据分为三个部分... 阅读详情

相关推荐

Netty面试深度解析:从核心原理到实战应用,助你拿下Java后端Offer

在网络编程领域,I/O模型和并发处理是构建高性能服务的基础。Java NIO提供了非阻塞I/O能力,但其原生API复杂且易错。Netty作为异步事件驱动框架,通过Reactor线程模型和高效的内存管理机制,解决了高并发场景下的性能与开发效率问题。其核心价值在于提供了易于扩展的管道处理器链(ChannelPipeline)和零拷贝优化,显著提升了网络应用的吞吐量与响应速度。这些特性使其在RPC框架通信层、即时通讯、物联网等需要处理海量连接与数据的应用场景中成为首选技术。本文聚焦于Netty的线程模型与内存管理

weixin_34293911的博客 317

Netty ByteBuf 按位读操作

前言 最近与一个刚接触Netty的学生关于Netty读字节流方面的操作进行讲解,可能对后来同学有点点帮助,所以整理出来供大家探讨。 ByteBuf读操作 ByteBuf读操作我们常用的有一下几种: ByteBuf.readByte() 读一个字节,有符号 ByteBuf.readUnsignedByte() 读一个字节,无符号 ByteBuf.readShort()读连续的两个字节,有符号 ByteBuf....

谁念西风独自凉 6312

Netty面试核心:从网络编程原理到高并发实战调优

网络编程是构建高并发分布式系统的基石,其核心在于解决传统阻塞IO模型在应对海量连接时的性能瓶颈。通过多路复用技术,一个线程可以高效管理多个网络连接,大幅减少线程资源消耗。在此基础上,Reactor线程模型进一步将连接建立与数据处理解耦,形成了高性能网络框架的骨架。Netty作为Java领域最主流的NIO框架,其价值在于将复杂的底层网络通信抽象为Channel、EventLoop、Pipeline等核心组件,并通过零拷贝、内存池等机制优化数据传输效率。在实际应用中,Netty不仅解决了粘包拆包、内存泄漏等工程

weixin_33795093的博客 455

Netty:ByteBuf写入数据、读出数据

Netty:ByteBuf写入数据、读出数据

听海边涛声 7825

Netty :仿写微信 IM 即时通讯系统

最近公司要自研聊天系统,开始撸代码...

知识改变命运,ヾ(◍°∇°◍)ノ゙【求关注】 812

K-L展开 (Karhunen-Loeve expansion)

K-L变换

susan_wang1的博客 2万+

ByteBuf 操作

public static void main(String[] args) throws UnsupportedEncodingException { // 1.创建一个非池化的ByteBuf,大小为14个字节 ByteBuf buffer = Unpooled.buffer(14); System.out.println("1.创建一个非池化的ByteBuf,大小为14个字节"); System.out.println("ByteBuf空间大小:" + buffer.ca...

weixin_40118044的博客 1836

WSL2+Docker+Ollama:解锁Windows本地GPU加速运行DeepSeek-R1模型

本文详细介绍了在Windows系统上,通过WSL2、Docker和Ollama的组合方案,实现本地GPU加速运行DeepSeek-R1模型的全过程。该方案解决了Windows环境下Ollama默认无法调用NVIDIA显卡的痛点,通过配置Docker的GPU支持,强制将计算任务分配给GPU,从而显著提升文本生成速度与效率,为开发者提供了一个便捷的本地AI测试环境。

weixin_28452161的博客 358

Bytebuf的读使用

Bytebuf的使用 首先,bytebuf有两种索引,分别是读索引(reader)和写索引(writer), 读索引<=写索引 reader是顺序读,表示从索引的位置按顺序往下读, 可以使用buf.readerindex(3)将读索引设置为3,然后接着顺序读。 同样可以使用get方法直接从指定位置顺序读: buf.getFloat(4):从索引为4的位置读一个Float的数(Float为4个字节,相当于把索引4-8的字节以float的形式读出来) bytebuf同样存在一个计数器,每次操作都会使计数器

guoqu1919的博客 2776

chipseeker Y叔

这一次讲解非常重要的peak注释,注释在ChIPseeker里只需要用到一个函数annotatePeak,它可以满足大家各方面的需求。 输入 当然需要我们上次讲到的BED文件,ChIPseeker自带了5个BED文件,用getSampleFiles()可以拿到文件的全路径,它返回的是个named list,我这里取第4个文件来演示。annotatePeak的输入也可以是GRanges对象,你如果用R做peak calling的话,直接就可以衔接上ChIPseeker了。 require(ChIPseeke

生信小博士的博客 1590

PCL读取点云数据报错:Failed to find match for field ‘x‘/ ‘y‘/ ‘z‘.

原因:使用matlab生成的pcd文件,点云数据是双精度类型,pcl处理的点云数据是单精度类型。解决方案:使用matlab生成的点云坐标单精度化,然后在生成点云加以存储。

little_white138的博客 871

netty—数据传输载体ByteBuf 中的getbyte()、getshort()、getint()

转载一篇文章,解决了我的一些疑惑,原文链接: https://blog.csdn.net/Qgwperfect/article/details/102492214 问题: 目前自学Netty中,正好学到数据传输载体ByteBuf的使用,对于其中的get方法获取到的值不理解。 先输入byte类型的1、2、3、4,再输入int类型的12,最后输入byte类型的5、6。 输出buffer.getByte(3)=4,这个很容易理解,接下来我就懵逼了。 输出buffer.getShort(3)=1024,why? 输

qq_37786081的博客 2378

优雅谈大模型:“System2”与“System 1”

研究人员探索了三种System 2方法——RaR、S2A 和 BSM,这些方法已经成功提炼到新的LLM,这个新的模型与System 1相比,产生了更好的结果,而且成本低于System 2。然而这种方法是有局限性,只能适用于特定的任务。

鲁班模锤 5171

netty——数据传输载体ByteBuf 中的getbyte()、getshort()、getint()

问题: 目前自学Netty中,正好学到数据传输载体ByteBuf的使用,对于其中的get方法获取到的值不理解。 先输入byte类型的1、2、3、4,再输入int类型的12,最后输入byte类型的5、6。 输出buffer.getByte(3)=4,这个很容易理解,接下来我就懵逼了。 输出buffer.getShort(3)=1024,why? 输出buffer.getInt(3)=671...

愚者 6178

100天精通Python(爬虫篇)——第118天:selenium自动化操作浏览器基础大总结

一、Selenium框架环境搭建 1. 下载模块 2. 安装浏览器驱动WebDriver 二、基础操作 1. 打开浏览器 2. 无界面模式 3. 元素定位 4. 元素操作 5. 前进后退 6. 执行js 7.页面等待 隐式等待(常用) 显式等待(了解) 三、进阶操作 1. 使用代理ip 2. 修改请求头 3. 隐藏指纹特征.....................

努力让自己发光,对的人才能迎着光而来 10万+

【AirPlay】苹果认证MFI学习

配件认证是一个过程,通过这个过程,可验证其配件符合MFi技术规范,并通过苹果指定的任何认证测试。MFi门户中的产品计划 "认证 "页面将指导你完成特定配件所需的认证步骤,并指出何时完成所有要求。在完成所有MFi认证要求之前,你不得制造、分发或销售任何配件。在开始MFi认证过程之前,你必须测试你的配件,以确保它符合最新的MFi技术规范,通过产品计划 "测试计划 "上的所有适用测试,并与它将声称具有兼容性的每个苹果设备兼容。

天天的博客 2277

IO编程(五)Netty编程入门(Netty数据传输载体 ByteBuf)

Netty 里面数据读写是以 ByteBuf 为单位进行交互 ByteBuf结构 ByteBuf 中每读取一个字节,readerIndex 自增1,ByteBuf 里面总共有 writerIndex-readerIndex 个字节可读, 由此可以推论出当 readerIndex 与 writerIndex 相等的时候,ByteBuf 不可读 写数据是从 writerIndex 指向的...

踟蹰千年的博客 532

2026年北京君正数字IC笔试试卷带答案

本文摘要:该文档是一份数字IC设计相关的考试试题,包含单选题、多选题、波形分析题和代码设计题。内容涵盖时序约束、半导体工艺、状态机设计、逻辑综合、异步FIFO设计等知识点。试题解析详细,重点考察数字电路基础、时序分析和Verilog代码实现能力。典型题目包括多周期路径设置、Moore/Mealy状态机区别、同步复位与异步复位特性、RISC-V架构特点等,并提供了异步FIFO的Verilog实现参考代码。(149字)

Open 114

Netty实战 IM即时通讯系统(七)数据传输载体ByteBuf介绍

##Netty实战 IM即时通讯系统(七)数据传输载体ByteBuf介绍 零、 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 客户端启动流程 实战: 客户端和服务端双向通信 数据传输载体ByteBuf介绍 客户端与服务端通信协议编解码 实现客户端登录 实现客户端与服务端收发消息 pipeline与channelHandler 构建客户端与服务端pipeline ...

chou_out_man的博客 1024

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

《netty入门与实战》笔记-03:数据传输载体 ByteBuf 介绍

为什么80%的码农都做不了架构师?>>> ...

weixin_33906657的博客 336

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Netty高性能网络编程实战:从核心原理到生产环境避坑指南

高性能网络编程是构建高并发、低延迟分布式系统的核心技术基础。其核心原理在于采用异步事件驱动模型,通过Reactor模式将连接管理与事件处理解耦,从而用少量线程支撑海量连接,大幅提升系统吞吐量。这一技术价值在微服务通信、游戏服务器、即时通讯等对实时性要求极高的应用场景中尤为凸显。Netty作为这一领域的标杆框架,通过其精妙的Channel、EventLoop、Pipeline与ByteBuf等组件,将高性能网络编程范式工程化、标准化。本文聚焦Netty的核心架构与实战,深入剖析其事件驱动模型与零拷贝机制,并针

weixin_34082854的博客 413

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Netty面试深度指南:从原理到实战,构建高并发网络编程能力

在网络编程与高并发系统设计中,Reactor模型和NIO(非阻塞I/O)是构建高性能服务端的基础架构思想。其核心原理在于通过事件驱动和异步处理,有效管理海量连接,避免传统阻塞I/O的资源浪费。这一技术价值直接体现在能够支撑如即时通讯(IM)、API网关和分布式RPC框架等高流量、低延迟的应用场景。Netty作为对这一模型的卓越实现,通过其高效的线程模型、零拷贝机制和内存池化技术,成为Java后端开发中处理网络通信的事实标准。掌握Netty的线程模型规划、ByteBuf内存管理以及应对粘包拆包等工程实践,是解

weixin_34326558的博客 388

第三章Netty应用上学习笔记

一、Netty是什么?为什么要用Netty? Netty是由JBOSS提供的一个java开源框架,现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。 也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端...

hankin的博客 442

Netty的核心组件

Netty是什么?   Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程...

weixin_30394633的博客 207

Netty ChannelHandlerContext 深度解析:事件传播、线程模型与避坑指南

在网络编程中,事件驱动模型是高并发服务端设计的核心思想之一。Netty作为Java领域最主流的异步网络框架,将这一思想具象化为ChannelPipeline链式处理机制,而ChannelHandlerContext正是串联整条链路的关键执行上下文。它同时绑定了Channel、ChannelPipeline与ChannelHandler,承担着入站/出站事件传播、线程模型约束、动态链路调整等核心职责。理解ChannelHandlerContext的原理,不仅有助于掌握fireChannelRead与write

weixin_33889245的博客 396
上一篇: Netty(3)-实现客户端与服务端的双向通信
下一篇: Netty(5)-自定义通信协议包的编码解码
BoringRong
BoringRong 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 2万+粉丝 386原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringRong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值