05-netty基础-ByteBuf数据结构

1 基本概念

在网络编程中,字节数据的处理是核心环节之一。无论是客户端与服务器之间的通信,还是数据的编解码操作,都离不开对字节缓冲区的高效管理。Java 原生的 ByteBuffer 虽然提供了基础功能,但在灵活性、性能和易用性上存在诸多局限。而 Netty 框架提供的 ByteBuf 则彻底解决了这些问题,成为处理网络字节数据的首选工具。

2 为什么需要 Bytebuf

Java 原生的 ByteBuffer 存在以下明显短板:

  • 单指针设计:仅有一个 position 指针,读写操作需频繁调用 flip() 切换模式,容易出错;
  • 固定容量:创建后容量不可动态调整,超出容量时需手动扩容,操作繁琐;
  • 内存管理复杂:堆外内存(直接内存)的释放依赖 GC,可能导致内存泄漏;
  • API 设计不友好:缺乏直接读写基本类型、字符串的便捷方法。

相比之下,ByteBuf 针对网络编程场景进行了全面优化:

  • 采用双指针设计,读写无需切换模式;
  • 支持自动扩容,无需手动处理容量不足问题;
  • 内置引用计数机制,精准控制内存生命周期;
  • 提供丰富的 API,简化字节数据操作。

3 Bytebuf数据结构

 3.1 创建一个空Bytebuf

 public static void main(String[] args) {// 空ByteBufemptyByteBuf();}private static void emptyByteBuf() {// byteBuf 分配一块内存,自动判断是否分配堆内存或者堆外内存ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();printMsg(byteBuf);}private static void printMsg(ByteBuf byteBuf) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("read index:").append(byteBuf.readerIndex()).append("\n");stringBuilder.append("write index:").append(byteBuf.writerIndex()).append("\n");stringBuilder.append("capacity:").append(byteBuf.capacity()).append("\n");stringBuilder.append("maxCapacity:").append(byteBuf.maxCapacity()).append("\n");ByteBufUtil.appendPrettyHexDump(stringBuilder, byteBuf);System.out.println(stringBuilder.toString());}

输出

read index:0
write index:0
capacity:256
maxCapacity:2147483647 

数据为空时bytebuf的内存结构

3.2 往Bytebuf中写入数据 

 private static void writeByte() {// byteBuf 分配一块内存,自动判断是否分配堆内存或者堆外内存ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();// 写入1个字节byteBuf.writeBytes(new byte[]{(byte)1});printMsg(byteBuf);}private static void printMsg(ByteBuf byteBuf) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("read index:").append(byteBuf.readerIndex()).append("\n");stringBuilder.append("write index:").append(byteBuf.writerIndex()).append("\n");stringBuilder.append("capacity:").append(byteBuf.capacity()).append("\n");stringBuilder.append("maxCapacity:").append(byteBuf.maxCapacity()).append("\n");ByteBufUtil.appendPrettyHexDump(stringBuilder, byteBuf);System.out.println(stringBuilder.toString());}

read index:0
write index:1
capacity:256
maxCapacity:2147483647
+-------------------------------------------------+
|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 01                                              |.               |
+--------+-------------------------------------------------+----------------+

 写入1个字节内存结构

3.3 Bytebuf中读取数据  

private static void readByte() {// byteBuf 分配一块内存,自动判断是否分配堆内存或者堆外内存ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();// 写入1个字节byteBuf.writeBytes(new byte[]{(byte)1, (byte)2});printMsg(byteBuf);// 读取1个字节byte b = byteBuf.readByte();printMsg(byteBuf);}private static void printMsg(ByteBuf byteBuf) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("read index:").append(byteBuf.readerIndex()).append("\n");stringBuilder.append("write index:").append(byteBuf.writerIndex()).append("\n");stringBuilder.append("capacity:").append(byteBuf.capacity()).append("\n");stringBuilder.append("maxCapacity:").append(byteBuf.maxCapacity()).append("\n");ByteBufUtil.appendPrettyHexDump(stringBuilder, byteBuf);System.out.println(stringBuilder.toString());}

read index:0
write index:2
capacity:256
maxCapacity:2147483647
+-------------------------------------------------+
|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 02                                           |..              |
+--------+-------------------------------------------------+----------------+
read index:1
write index:2
capacity:256
maxCapacity:2147483647
+-------------------------------------------------+
|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 02                                              |.               |
+--------+-------------------------------------------------+----------------+

 

 3.4 Bytebuf读取后重复读取

 public static void main(String[] args) {// jvm堆内存ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();// 写数据byteBuf.maxWritableBytes();byteBuf.writeBytes(new byte[] {1, 2, 3, 4});printMsg(byteBuf);// 重置,写指针复位到起始位置重新写入,覆盖写byteBuf.resetWriterIndex();byteBuf.writeInt(6);printMsg(byteBuf);// 读byteBuf.markReaderIndex();byte a = byteBuf.readByte();byte b = byteBuf.readByte();byteBuf.resetReaderIndex();printMsg(byteBuf);}private static void printMsg(ByteBuf byteBuf) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("read index:").append(byteBuf.readerIndex()).append("\n");stringBuilder.append("write index:").append(byteBuf.writerIndex()).append("\n");stringBuilder.append("capacity:").append(byteBuf.capacity()).append("\n");stringBuilder.append("maxCapacity:").append(byteBuf.maxCapacity()).append("\n");ByteBufUtil.appendPrettyHexDump(stringBuilder, byteBuf);System.out.println(stringBuilder.toString());}

read index:0
write index:4
capacity:256
maxCapacity:2147483647
+-------------------------------------------------+
|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 02 03 04                                     |....            |
+--------+-------------------------------------------------+----------------+
read index:0
write index:8
capacity:256
maxCapacity:2147483647
+-------------------------------------------------+
|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 01 02 03 04 01 02 03 04                         |........        |
+--------+-------------------------------------------------+----------------+
read index:0
write index:4
capacity:256
maxCapacity:2147483647
+-------------------------------------------------+
|  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 00 00 00 06                                     |....            |
+--------+-------------------------------------------------+----------------+

 

 备注:markWriterIndex、resetWriterIndex一般是配套使用,如果未标记写指针的位置默认从起始位置开始;markReaderIndex、resetReaderIndex一般也是配套使用,如果未标记读取的位置,则从起始位置重新读取

4 Bytebuf扩容

  1. 初始尝试:如果 minNewCapacity 小于等于 4MB(4194304 字节),新容量为大于等于 minNewCapacity 的最小 2 的幂;
  2. 超过 4MB 时:如果 minNewCapacity 大于 4MB,新容量为大于等于 minNewCapacity 且为 4MB 整数倍的值;
  3. 上限控制:新容量不能超过 ByteBuf 的最大容量。

案例: 未超过4M,成倍增长

public class ByteBufCapacity {public static void main(String[] args) {// jvm堆内存ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();for (int i=0; i<256; i++) {byteBuf.writeBytes(new byte[] {(byte) i});}printMsg(byteBuf);for (int i=0; i<256; i++) {byteBuf.writeBytes(new byte[] {(byte) i});}printMsg(byteBuf);}private static void printMsg(ByteBuf byteBuf) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("read index:").append(byteBuf.readerIndex()).append("\n");stringBuilder.append("write index:").append(byteBuf.writerIndex()).append("\n");stringBuilder.append("capacity:").append(byteBuf.capacity()).append("\n");stringBuilder.append("maxCapacity:").append(byteBuf.maxCapacity()).append("\n");
//        ByteBufUtil.appendPrettyHexDump(stringBuilder, byteBuf);System.out.println(stringBuilder.toString());}

read index:0
write index:256
capacity:256
maxCapacity:2147483647

read index:0
write index:512
capacity:512
maxCapacity:2147483647

 大于4M,每次增加4M扩容

package com.bonnie.netty.bytebuf;import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;public class ByteBufCapacity {public static void main(String[] args) {// jvm堆内存ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();// 4Mfor (int i=0; i<4194304; i++) {byteBuf.writeBytes(new byte[] {(byte) i});}printMsg(byteBuf);// 扩容+4Mfor (int i=0; i<4194304; i++) {byteBuf.writeBytes(new byte[] {(byte) i});}printMsg(byteBuf);// 扩容+4Mfor (int i=0; i<4194304; i++) {byteBuf.writeBytes(new byte[] {(byte) i});}printMsg(byteBuf);}private static void printMsg(ByteBuf byteBuf) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("read index:").append(byteBuf.readerIndex()).append("\n");stringBuilder.append("write index:").append(byteBuf.writerIndex()).append("\n");stringBuilder.append("capacity:").append(byteBuf.capacity()).append("\n");stringBuilder.append("maxCapacity:").append(byteBuf.maxCapacity()).append("\n");
//        ByteBufUtil.appendPrettyHexDump(stringBuilder, byteBuf);System.out.println(stringBuilder.toString());}}

read index:0
write index:4194304
capacity:4194304
maxCapacity:2147483647

read index:0
write index:8388608
capacity:8388608
maxCapacity:2147483647

read index:0
write index:12582912
capacity:12582912
maxCapacity:2147483647

 5 堆内存和堆外内存

实堆内的意思就是java虚拟机里面的堆空间,而堆外的意思是java进程中系统 为它分配的堆空间,jvm堆中的数据如果想要写入磁盘,就会进行write系统调用,调用过程为:jvm堆->系统 堆->PageCache->磁盘,如果数据是放在系统heap中,调用过程为:系统堆->PageCache->磁盘。 我们可以看到,使用堆内内存写入数据会少一次的拷贝次数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91582.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Nginx反向代理】通过Nginx反向代理将多个后端server统一到同一个端口上的方法

文章目录前言解决方案&#xff1a;使用 Nginx 做统一反向代理前言 在多人开发任务中&#xff0c;如果不同人负责不同的后端接口服务开发&#xff0c;那么就面临着每个人的服务部署到不同的端口上&#xff0c;甚至有的人的服务部署在不同的服务器上。这时候前端如果想要调用后端…

Chrontel【CH7219A-BF】CH7219A USB-C和DP 1.4至HDMI 2.1协议转换器,带DSC解码功能

G通用 D描述Chrontel 的 CH7219A 是一种低成本、低功耗的半导体器件 通过 USB Type-C 将 DisplayPort 信号转换为 HDMI 2.0 连接器。这款基于 USB Type-C 的创新型 DisplayPort 接收器具有高 高性能DSC解码器&#xff0c;集成HDMI 2.0发射器 专为 USB Type-C 转 HDMI 2.0 转换器…

疯狂星期四文案网第26天运营日记

网站运营第26天&#xff0c;点击观站&#xff1a; 疯狂星期四 crazy-thursday.com 全网最全的疯狂星期四文案网站 运营报告 今日访问量 30多ip,断崖式下跌&#xff0c;习惯了。。 今日搜索引擎收录情况 必应52个页面&#xff0c;比昨日12 百度仍然只有首页 谷歌收录正常 …

元策联盈:深耕金融领域,赋能行业发展​

元策联盈&#xff1a;深耕金融领域&#xff0c;赋能行业发展元策联盈在金融行业的深耕细作&#xff0c;不仅体现在为客户提供优质服务上&#xff0c;更在于其对行业发展的积极推动和自身的不断创新突破。行业贡献与社会责任元策联盈始终将社会责任融入企业发展的血脉之中。在助…

力扣-字母异位词

这里我也是没有太懂&#xff0c;只懂个大概&#xff0c;先统计p和当前窗口的字符&#xff0c;后主要在窗口大小固定为 p.length()&#xff0c;在 s 上滑动做文章&#xff0c;在s里找到p的长度大小&#xff0c;最后直接比较两个频率数组来判断异位词定长窗口做法class Solution …

华为数通HCIP

华为认证数通方向的 HCIP&#xff08;华为认证 ICT 高级工程师&#xff09;考试难度适中&#xff0c;既不像 HCIA&#xff08;初级&#xff09;那样侧重基础概念&#xff0c;也不像 HCIE&#xff08;专家级&#xff09;需要复杂的综合实验和面试&#xff0c;但仍需要系统的知识…

在SQL SERVER 中,用SSMS 实现存储过程的每日自动调用

在 SQL Server Management Studio (SSMS) 中实现每日自动调用存储过程&#xff0c;需通过 ​​SQL Server 代理作业​​配置定时任务。以下是详细操作步骤&#xff1a;&#x1f527; 一、启用 SQL Server 代理服务&#xff08;前置条件&#xff09;​​启动服务​​&#xff1a…

赛博算命之八字测算事业运势的Java实现(四柱、五行、十神、流年、格局详细测算)

个人主页-爱因斯晨 文章专栏-赛博算命 最近学习人工智能时遇到一个好用的网站分享给大家&#xff1a; 人工智能学习 文末有投票&#xff0c;评论区有红包哦&#xff01; 前言 在前段时间更新了赛博算命系列&#xff0c;出乎我的意料反响很好。也受到广大网友的赞赏&#xff0…

2025 腾讯广告算法大赛 Baseline 项目解析

项目概述 2025 腾讯广告算法大赛 Baseline&#xff0c;一个简单的序列推荐系统&#xff0c;主要用于建模用户和物品的交互序列&#xff0c;并利用多模态特征&#xff08;文本、图像等 embedding&#xff09;来提升推荐效果。 核心文件功能 1. main.py - 主训练脚本 负责模型训练…

数据结构(11)栈和队列算法题 OVA

一、概念与结构 循环队列是一种特殊的队列&#xff0c;首尾相连成环&#xff0c;也叫环形队列。环形队列具有以下三个特点&#xff1a; &#xff08;1&#xff09;队头删除数据&#xff0c;队尾插入数据。 &#xff08;2&#xff09;给定固定的空间&#xff0c;使用过程中不…

九联UNT403HS_海思MV320处理器_安卓9-优盘强刷刷机包

九联UNT403HS_海思MV320处理器_安卓9-优盘强刷刷机包前言&#xff1a;九联UNT403HS&#xff0c;海思MV320芯片&#xff0c;已知有2种内存型号&#xff0c;分别是28G和216G。已知河南融合版本是28G&#xff0c;广东版好像既有28G又有216G。理论上固件没有本质区分&#xff0c;能…

Xilinx高性能低延时PCIe-DMA控制器IP,SGDMA,QDMA,RDMA,CDMA,V4L2驱动,视频采集、AD采集

Multi-Channel High Performance PCIe QDMA&RDMA IP介绍基于PCI Express Integrated Block&#xff0c;Multi-Channel PCIe QDMA Subsystem实现了使用DMA地址队列的独立多通道、高性能Continous&#xff08;CDMA&#xff09;或Scather Gather DMA&#xff08;SGDMA&#xf…

10、Docker Compose 安装 MySQL

&#x1f433; 使用 Docker Compose 安装 MySQL&#xff08;含配置详解与常见问题&#xff09;标签&#xff1a;#DockerCompose #MySQL #数据库部署 #后端开发 #运维入门 #配置详解 适合读者&#xff1a;开发者、DevOps、新手运维人员&#x1f4cc; 一、前言 在日常开发与部署中…

Dynamic A(D)算法深度剖析:动态环境下的路径规划革新

Dynamic A*(D*)算法深度剖析:动态环境下的路径规划革新 文章目录 Dynamic A*(D*)算法深度剖析:动态环境下的路径规划革新 1. 引言:动态路径规划的核心挑战与解决方案 1.1 动态环境的本质特征 1.2 D * 算法的诞生与核心价值 2. D * 算法核心原理深度解析 2.1 反向搜索机制…

前端框架Vue3(四)——组件通信及其他API

组件通信组件关系传递方式父传子1. props2. v-model3. $refs4. 默认插槽、具名插槽子传父1.props2.自定义事件3.v-model4.parent5.作用域插槽祖传孙、孙传祖1.$attrs2.provide、inject兄弟间、任意组件间1.mitt2.pinia【props】 概述&#xff1a;props是使用频率最高的一种通信…

07【C++ 初阶】类和对象(中篇) --- 类的默认成员函数

文章目录前言类的6个默认成员函数1.构造函数1.1 构造函数特性1.1.1 函数名与类名相同1.1.2 无返回值1.1.3 对象实例化时编译器自动调用对应的构造函数1.1.4 构造函数可以重载1.1.5 默认构造只能有一个1.1.6 默认构造的必要性1.2 构造函数的初始化列表2.析构函数2.1 析构函数特性…

第二次CISSP考试通过!

今天我终于临时通过了 CISSP 考试&#xff01;这第二次的精神压力一点也不比第一次小。我在第 101 道题 时通过&#xff0c;还剩大约 30 分钟。我当时真的以为自己又要像上次那样时间不够了。第一次考试的失败经历&#xff1a;第一次考试是我刚参加完为期 5 天的强化 Boot Camp…

USRP捕获手机/路由器数据传输信号波形(上)

目录&#xff1a; USRP捕获手机/路由器数据传输信号波形&#xff08;上&#xff09; USRP捕获手机/路由器数据传输信号波形&#xff08;中&#xff09; USRP捕获手机/路由器数据传输信号波形&#xff08;下&#xff09; 一、前期准备 1.1 场景与系统 手机、路由器与天线的…

基于STM32F103的FM1702驱动程序

基于STM32F103微控制器与复旦微电子FM1702SL射频读卡芯片的驱动开发方案&#xff0c;整合了硬件配置、寄存器操作和通信协议实现&#xff1a;一、硬件连接设计 1. 管脚映射表FM1702SL引脚STM32F103引脚功能说明VDD3.3V电源输入GNDGND地线SCKPA5(SPI1_SCK)SPI时钟MISOPA6(SPI1_M…

京东商品评论API指南

一、引言京东商品评论API(JD.item_review)是京东开放平台提供的重要接口&#xff0c;允许开发者获取商品的详细评论数据。通过该接口可以获取包括评论内容、评分、评论时间、用户昵称等信息&#xff0c;为商品分析、用户行为研究等提供数据支持‌。二、接口概述1. 接口基本信息…