ByteBuf的扩容机制

ByteBuf使用详解:ByteBuff组成、扩容、retain、release、零拷贝(slice、duplicate、compositeByteBuf、unpolled)、深拷贝。 ByteBuf是对字节数据的封装。是netty的Server与Client之间通信的数据传输载体(Netty的数据容器),它提供了一个byte数组(byte[])的抽象视图,既解决了JDK API的局限性,又为网络应用程序的开发者提供了更好的API。ByteBuf使用详解:ByteBuff组成、扩容、retain、release、零拷贝(slice、duplicate、compositeByteBuf、unpolled)、深拷贝。 阅读详情

Netty ByteBuf 的扩容机制主要由 AbstractByteBuf 类及其子类中的 ensureWritable 方法及其相关逻辑控制,并受到 ByteBufAllocator 和 RecvByteBufAllocator(特别是 AdaptiveRecvByteBufAllocator)的影响。

1. 扩容触发条件

当调用 ByteBuf 的写入方法(如 writeBytes、writeInt 等),如果写入的数据量超过了当前 ByteBuf 的可写容量(writableBytes()),就会触发扩容操作。以下是一个简单示例:

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class ByteBufExpandExample {
    public static void main(String[] args) {
        ByteBuf buffer = Unpooled.buffer(10); // 初始容量为 10
        System.out.println("初始容量: " + buffer.capacity());
        byte[] data = new byte[20];
        try {
            buffer.writeBytes(data); // 尝试写入 20 字节数据,会触发扩容
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("扩容后容量: " + buffer.capacity());
        buffer.release();
    }
}

2. 核心扩容方法

ByteBuf 的扩容主要通过 capacity(int newCapacity) 方法实现,不同的 ByteBuf 实现类会重写该方法来实现具体的扩容逻辑。以下是一些常见 ByteBuf 实现类的 capacity 方法:

2.1 UnpooledHeapByteBuf
@Override
public ByteBuf capacity(int newCapacity) {
    checkNewCapacity(newCapacity);
    byte[] oldArray = array;
    int oldCapacity = oldArray.length;
    if (newCapacity == oldCapacity) {
        return this;
    }

    int bytesToCopy;
    if (newCapacity > oldCapacity) {
        bytesToCopy = oldCapacity;
    } else {
        trimIndicesToCapacity(newCapacity);
        bytesToCopy = newCapacity;
    }
    byte[] newArray = allocateArray(newCapacity);
    System.arraycopy(oldArray, 0, newArray, 0, bytesToCopy);
    setArray(newArray);
    freeArray(oldArray);
    return this;
}
  • 逻辑说明:首先检查新容量是否合法,然后比较新容量和旧容量。如果新容量大于旧容量,将旧数组中的数据复制到新数组;如果新容量小于旧容量,先调整读写索引,再复制数据。最后释放旧数组,设置新数组。
2.2 PooledByteBuf
@Override
public final ByteBuf capacity(int newCapacity) {
    if (newCapacity == length) {
        ensureAccessible();
        return this;
    }
    checkNewCapacity(newCapacity);
    if (!chunk.unpooled) {
        if (newCapacity > length) {
            if (newCapacity <= maxLength) {
                length = newCapacity;
                return this;
            }
        } else if (newCapacity > maxLength >>> 1 &&
                (maxLength > 512 || newCapacity > maxLength - 16)) {
            length = newCapacity;
            trimIndicesToCapacity(newCapacity);
            return this;
        }
    }

    PooledByteBufAllocator.onReallocateBuffer(this, newCapacity);
    chunk.arena.reallocate(this, newCapacity);
    return this;
}
  • 逻辑说明:先检查新容量是否等于当前长度,如果是则直接返回。然后检查新容量是否在合适的范围内,如果是则更新长度并返回。否则,调用 PooledByteBufAllocator 和 ChunkArena 的相关方法进行重新分配。

3. 计算新容量的策略

在进行扩容时,需要计算新的容量。ByteBufAllocator 提供了 calculateNewCapacity 方法来计算新容量,不同的 ByteBufAllocator 实现类会重写该方法以实现不同的计算逻辑。例如,AbstractByteBufAllocator 的实现如下:

@Override
public int calculateNewCapacity(int minNewCapacity, int maxCapacity) {
    checkPositiveOrZero(minNewCapacity, "minNewCapacity");
    if (minNewCapacity > maxCapacity) {
        throw new IllegalArgumentException(String.format(
                "minNewCapacity: %d (expected: not greater than maxCapacity(%d)",
                minNewCapacity, maxCapacity));
    }
    final int threshold = CALCULATE_THRESHOLD; // 4 MiB page

    if (minNewCapacity == threshold) {
        return threshold;
    }

    // 如果超过阈值,不进行双倍扩容,而是按阈值增加
    if (minNewCapacity > threshold) {
        int newCapacity = minNewCapacity / threshold * threshold;
        if (newCapacity > maxCapacity - threshold) {
            newCapacity = maxCapacity;
        } else {
            newCapacity += threshold;
        }
        return newCapacity;
    }

    // 64 <= newCapacity 是 2 的幂次方 <= 阈值
    final int newCapacity = MathUtil.findNextPositivePowerOfTwo(Math.max(minNewCapacity, 64));
    return Math.min(newCapacity, maxCapacity);
}
  • 逻辑说明

    :

    • 首先检查最小新容量是否合法,是否超过最大容量。
    • 如果最小新容量等于阈值(4 MiB),则直接返回阈值。
    • 如果最小新容量超过阈值,不进行双倍扩容,而是按阈值增加。
    • 如果最小新容量小于阈值,将其调整为不小于 64 且是 2 的幂次方的数。
    • 最后返回不超过最大容量的新容量。

4. 总结

Netty 的 ByteBuf 扩容机制通过不同的实现类和方法,提供了灵活且高效的内存管理方案。在实际使用中,可以根据具体的需求选择合适的 ByteBuf 实现类和扩容策略,以提高系统的性能和稳定性。同时,了解扩容机制有助于更好地使用 ByteBuf,避免不必要的内存开销和性能问题。

聊一聊 Netty 数据搬运工 ByteBuf 体系的设计与实现(上) 时光芿苒,岁月如梭,好久没有给大家更新 Netty 相关的文章了,在断更 Netty 的这段日子里,笔者一直在持续更新,目前为止,算是将 Linux 内存管理子系统相关的主干源码较为完整的给大家呈现了出来,同时也结识了很多喜欢内核的读者,经常在后台留言讨论一些代码的设计细节,在这个过程中,我们相互分享,相互学习,浓浓的感受到了大家对技术那份纯粹的热爱,对于我自己来说,也是一种激励,学习,提高的机会。 阅读详情

相关推荐

Netty的bytebuf详解

Netty的bytebuf详解

weixin_59244784的博客 818

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

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

小工匠 7141

【踩坑记录】Latex引文bib报错

VScode+Texlive+Zotero本地论文写作环境踩坑。解决Zotero导出bib文件后tex中通过cite引用时所产生的问题。

weixin_43319948的博客 2823

记录一下netty ByteBuf扩容机制

喜欢阅读源码的朋友,可先去下载下netty的源码,从github中下载的速度太慢了,这里提供gitlee的下载地址 https://gitee.com/mirrors/netty?_from=gitee_search 我阅读的是netty4.1版本的源码,下载完成后别忘记了git checkout 4.1一下,切换到4.1分支的源码哦。 我们都知道ByteBuf类的继承结构图: 的一个...

qq_38796327的博客 1536

C语言面试,8道一定会遇到的----关于指针的笔试题详解

C语言面试,8道一定会遇到的----关于指针的笔试题详解

m0_55322924的博客 462

Latex下使用JabRef添加参考文献

文章目录 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结 前言 Latex可以手动添加参考文献,但文献过多时,使用JabRef软件相对方便。 提示:以下是本篇文章正文内容,下面案例可供参考 一、JabRef安装 网址:http://www.jabref.org 打开网址后,点击“Download” 进入如下页面后,选择 portable (便携版,无需安装),下载后是一压缩包,打开即可使用。 二、使用 1.创建库 ...

sz3076799的博客 3466

【Netty篇】ByteBuf 详解(中)

ByteBuf就是Netty世界里的数据搬运工、信息翻译官和临时存储中心!

qq_56158663的博客 1309

智慧工地算法视频分析服务器区域入侵检测AI视频分析技术在煤矿的实战应用

通过实时分析和处理井下视频资料,智慧矿山算法视频分析服务器不仅能够及时发现并预警人员违规行为和设备异常状况,还能够通过智能分析预防潜在的安全风险,从而显著提高煤矿的安全管理水平和生产效率。

EasyDarwin开源社区技术博客 559

ByteBuf动态扩容机制

package com.demo.study.socket.netty; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import java.util.Arrays; public class ByteBufDemo { public static void main(String[] args) { // 1.初始化bytebuf ByteBuf buffer = Unpoo.

qianhuan_的博客 2597

Cesium+Three.js融合实战:从零构建GIS与BIM一体化大场景

本文详细介绍了Cesium与Three.js融合技术在GIS与BIM一体化大场景中的应用实践。通过坐标系转换、双引擎协同渲染等核心技术,实现宏观地理信息与微观建筑细节的完美结合,为智慧城市、数字孪生等项目提供高效解决方案。文章包含环境配置、性能优化等实战经验,助力开发者快速掌握三维可视化开发技巧。

weixin_42563415的博客 259

几率大的Redis面试题(含答案)

本文的面试题如下: Redis 持久化机制 缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题 热点数据和冷数据是什么 Memcache与Redis的区别都有哪些? 单线程的redis为什么这么快 redis的数据类型,以及每种数据类型的使用场景,Redis 内部结构 redis的过期策略以及内存淘汰机制【~】 Redis 为什么是单线程的,优点 如何解决redis的并发竞争key问题 Red...

睶 38万+

网络|Netty的缓冲区容器ByteBuf的扩容机制

ByteBu简介        ByteBuf是我们使用netty中不可避免会用到的数据容器,在某种程度上,和我们java中的集合有很多相似之处,只不过集合用于盛装的数据是对象数据,但ByteBuf更多盛装的是byte,是一种缓存区的概念,但某种意义上来说他又是容器,既然是容器会不会和集合有相似之处能,比如扩容? Bytebuf...

xianghe_qqq的博客 1117

【深度学习时间序列预测案例】零基础入门经典深度学习时间序列预测项目实战(附代码+数据集+原理介绍)

本专栏整理了《深度学习时间序列预测案例》,内包含了各种不同的基于深度学习模型的时间序列预测方法,例如LSTM、GRU、CNN(一维卷积、二维卷积)、LSTM-CNN、BiLSTM、Self-Attention、LSTM-Attention、Transformer等经典模型,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。

优快云 精品推荐 4万+

Netty(三):零拷贝、空轮循bug和ByteBuf扩容机制

零拷贝 零拷贝是netty高性能设计的一个点,想要了解零拷贝,先要知道直接内存这个概念。 直接内存不是Java虚拟机中的一部分,他对应的是机器的物理内存。 以客户端向服务端发送数据为例,当client发送数据时,先由socket缓冲区接受数据,然后copy到机器的直接内存中,然后再由一些native方法将这些数据拷贝到JVM中,这个过程中就有两次拷贝。 而零拷贝是这样做的:以客户端向服务端发送数据为例,当client发送数据时,先由socket缓冲区接受数据,然后copy到机器的直接内存中,然后将这些

十拳剑 434

SI案例分享--考虑ESD保护二极管的差分线阻抗仿真

PCB设计中的cut out参考面早已是SI评估中常用的阻抗优化方式,通过合理的仿真建模,可以提供合适的设计参考,并保持与测试结果的高度一致性。

一只豌豆象的博客 1436

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

netty的bytebuf扩容机制

如果要写的数据+writeIndex没有大于64那么就返回64,如果超过了64没有超过4M就返回642,如果超过了642那么就是6422,如果等于4M,那么就返回4M,如果超过了4M,那么就是要写的数据/4*4+4. 由wirteIndex,writeIndex,capatity,替代nio的limit,position,capatity. ...

weixin_39507514的博客 1180

数学建模模型总结

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

netty的零拷贝、架构设计、ByteBuf扩容机制详解

文章目录1. netty高并发架构设计精髓 1. netty高并发架构设计精髓         netty作为客户端与服务端通信组件,可以支持极大的并发连接,那么它在处理高并发时有什么值得借鉴的设计思路呢? ①:主从Reactor线程模型 主从模型:用主线程组boosGroup中的NioEventLoop来接受请求,生成客户端channel,并把客户端channel注册到WorkerGroup中的NioEventLoop中去

qq_1149513559的博客 721

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

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

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

netty源码之ByteBuf详解

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

bobozai86的博客 9624

bytebuf池_图文分析ByteBuf是什么

ByteBuf是什么ByteBuf是Netty中非常重要的一个组件,他就像物流公司的运输工具:卡车,火车,甚至是飞机。而物流公司靠什么盈利,就是靠运输货物,可想而知ByteBuf在Netty中是多么的重要。没有了ByteBuf,Netty就失去了灵魂,其他所有的都将变得毫无意义。ByteBuf是由Byte和Buffer两个词组合成的一个词,但是因为JDK中已经有了一个ByteBuffer,并且使用...

weixin_39611413的博客 307

Netty源码阅读之ByteBuf简析(二)

前面对于Netty中的ByteBuf缓存做了一下简单的介绍,下面将围绕源码,对于其中的几个特性进行分析。 1.扩容机制 首先来聊下Bytebuf的扩容机制,这个机制也是Netty比较强悍的地方,而我们知道JDK自带的ByteBuffer是无法扩容的,在Bytebuf创建的时候,我们通常会设置一个初始容量,在我们写数据的时候,如果写指针超过了设置的初始容量,那么Bytebuf将进行扩容,废话不多说,下面我们直接通过源码来一探究竟吧: public ByteBuf writeBytes(ByteBuf

记忆碎片 1027

Netty从0到1系列之ByteBuf【中】

摘要: 本文是《Netty从0到1系列》关于ByteBuf的中篇,重点介绍ByteBuf的核心API与基础操作。通过代码示例演示了ByteBuf的创建、数据写入(含自动扩容)、读取、标记重置、搜索等核心功能,并展示了读写过程中的索引变化。文章强调使用后需释放资源,为后续高级特性讲解奠定基础。该系列已涵盖I/O模型、NIO、Selector等Netty核心组件,本篇是深入理解Netty数据缓冲机制的关键章节。

编程技术圈 1586

BAT面试必问细节:关于Netty中的ByteBuf详解

在Netty中,还有另外一个比较常见的对象ByteBuf,它其实等同于Java Nio中的ByteBuffer,但是ByteBuf对Nio中的ByteBuffer的功能做了很作增强,下面我们来简单了解一下ByteBuf。 下面这段代码演示了ByteBuf的创建以及内容的打印,这里显示出了和普通ByteBuffer最大的区别之一,就是ByteBuf可以自动扩容,默认长度是256,如果内容长度超过阈值时,会自动触发扩容 public class ByteBufExample { public stat

跟着Mic学架构 677

Netty零拷贝机制

1.Netty自己的ByteBuf ByteBuf是为解决ByteBuffer的问题和满足网络应用程序开发人员的日常需求而设计的。 1.1JDK ByteBuffer的缺点 无法动态扩容。长度是固定的,不能动态扩展和收缩,当数据大于ByteBuffer容量时,会发生索引越界异常。 API使用复杂。读写的时候需要手动调用flip()和rewind等方法,使用时需要十分谨慎的使用这些api,否则很容...

suvue 318

java 检查bytebuf长度_Java网络编程 -- Netty中的ByteBuf

由于JDK中提供的ByteBuffer无法动态扩容,并且API使用复杂等原因,Netty中提供了ByteBuf。Bytebuf的API操作更加便捷,可以动态扩容,提供了多种ByteBuf的实现,以及高效的零拷贝机制。ByteBuf的操作ByteBuf有三个重要的属性:capacity容量,readerIndex读取位置,writerIndex写入位置提供了readerIndex和weiterInd...

weixin_34261380的博客 710

Netty学习之ByteBuf

Netty学习之ByteBuf 简介 Netty是一个高性能、高可扩展性的异步事件驱动的网络应用程序框架,它极大地简化了TCP和UDP客户端和服务器开发等网络编程。 Netty重要的四个重要内容: 1)Reactor线程模型:一种高性能的多线程程序设计思路; 2)Netty中自己定义的Channel概念:增强版的通道概念; 3)ChannelPipeline责任链设计模式:事件处理机制; 4)内存...

lianmouren的博客 262

Netty应用(八) 之 ByteBuf & 半包粘包问题 & 半包粘包解决方案-封帧解码器

Netty应用(八) 之 ByteBuf & 半包粘包问题 & 半包粘包解决方案-封帧解码器

Eriksen的博客 2480
上一篇: Netty中ByteBuf的使用
下一篇: ByteBuf继承体系和每个类的作用
Jooou
博客等级 码龄9年 226粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值