Netty源码分析---Netty-ByteBuf核心详解-简化版

Netty源码分析系列之writeAndFlush()下 write()只会将数据只是发送到了ChannelOutboundBuffer 缓冲区中,还没有被发送到操作系统的套接字中只有当调用了 flush()方法后,才会真正将数据发送到套接字中。那么 flush()方法的源码又是如何执行的呢? 阅读详情

Netty ByteBuf 核心详解(简化版)

ByteBuf 是 Netty 对 ByteBuffer 的优化实现

一、为什么需要 ByteBuf?

1.1 ByteBuffer 的痛点

// ByteBuffer 使用繁琐
ByteBuffer buffer = ByteBuffer.allocate(10);
buffer.put("data".getBytes());
buffer.flip();              // 必须手动切换模式!
byte[] data = new byte[buffer.limit()];
buffer.get(data);
buffer.clear();             // 必须手动清理!

问题:

  • 读写模式需要手动切换(flip/clear/compact)
  • 只有一个 position 指针,不能同时读写
  • 容量固定,无法动态扩展
  • API 不友好,容易出错

1.2 ByteBuf 的优势

// ByteBuf 使用简单
ByteBuf buffer = Unpooled.buffer(10);
buffer.writeBytes("data".getBytes());  // 直接写
byte[] data = new byte[buffer.readableBytes()];
buffer.readBytes(data);                // 直接读,无需 flip!
buffer.clear();                        // 清理

优势:

  • ✅ 读写索引分离(readerIndex / writerIndex)
  • ✅ 无需手动切换读写模式
  • ✅ 支持自动扩容
  • ✅ 零拷贝支持
  • ✅ 引用计数管理内存
  • ✅ 链式调用,API 友好

二、ByteBuf 核心原理

2.1 双指针设计

ByteBuf 使用两个独立的索引:

0 <= readerIndex <= writerIndex <= capacity
属性作用
readerIndex读取位置指针
writerIndex写入位置指针
capacity缓冲区总容量

2.2 内存区域划分

+-------------------+------------------+------------------+
| discardable bytes |  readable bytes  |  writable bytes  |
|  (已读废弃区域)    |   (可读区域)      |   (可写区域)      |
+-------------------+------------------+------------------+
|                   |                  |                  |
0      <=      readerIndex   <=   writerIndex    <=    capacity

三个区域:

  1. discardable bytes:0 ~ readerIndex,已读数据,可丢弃
  2. readable bytes:readerIndex ~ writerIndex,可读数据
  3. writable bytes:writerIndex ~ capacity,可写空间

三、ByteBuf 使用流程图解

3.1 初始状态

创建: ByteBuf buffer = Unpooled.buffer(10);

[_][_][_][_][_][_][_][_][_][_]
 ↑
readerIndex=0
writerIndex=0
capacity=10

3.2 写入数据

buffer.writeBytes("ABCD".getBytes());

[A][B][C][D][_][_][_][_][_][_]
 ↑           ↑
readerIndex=0 writerIndex=4

关键点:

  • writerIndex 自动移动到 4
  • readerIndex 保持不变
  • 无需调用 flip()

3.3 读取数据

byte b1 = buffer.readByte();  // 读取 'A'
byte b2 = buffer.readByte();  // 读取 'B'

[A][B][C][D][_][_][_][_][_][_]
     ↑   ↑
readerIndex=2 writerIndex=4

关键点:

  • readerIndex 自动移动到 2
  • writerIndex 保持不变
  • 可读数据:writerIndex - readerIndex = 2

3.4 丢弃已读数据

buffer.discardReadBytes();  // 类似 ByteBuffer.compact()

[C][D][_][_][_][_][_][_][_][_]
 ↑   ↑
readerIndex=0 writerIndex=2

作用:

  • 将未读数据移到开头
  • 释放已读空间
  • 增加可写空间

四、ByteBuf vs ByteBuffer 对比

4.1 API 对比

操作ByteBufferByteBuf
创建ByteBuffer.allocate(10)Unpooled.buffer(10)
写入put(data)writeBytes(data)
切换模式flip() ⚠️无需切换 ✅
读取get(data)readBytes(data)
清空clear()clear()
压缩compact()discardReadBytes()

4.2 完整示例对比

ByteBuffer 方式:

ByteBuffer buffer = ByteBuffer.allocate(10);
buffer.put("ABCD".getBytes());
buffer.flip();  // ⚠️ 必须切换模式

byte[] data = new byte[buffer.limit()];
buffer.get(data);
System.out.println(new String(data));  // ABCD

buffer.clear();  // ⚠️ 必须清理

ByteBuf 方式:

ByteBuf buffer = Unpooled.buffer(10);
buffer.writeBytes("ABCD".getBytes());
// ✅ 无需 flip()

byte[] data = new byte[buffer.readableBytes()];
buffer.readBytes(data);
System.out.println(new String(data));  // ABCD

buffer.clear();

五、实战示例

5.1 基础读写示例

public class ByteBufBasicDemo {
    public static void main(String[] args) {
        // 1. 创建缓冲区
        ByteBuf buffer = Unpooled.buffer(10);
        System.out.println("初始状态:");
        printBuffer(buffer);
        // 输出: readerIndex=0, writerIndex=0, capacity=10
        
        // 2. 写入数据
        buffer.writeBytes("love".getBytes());
        System.out.println("\n写入 'love' 后:");
        printBuffer(buffer);
        // 输出: readerIndex=0, writerIndex=4, capacity=10
        
        // 3. 读取数据(逐字节)
        System.out.println("\n逐字节读取:");
        while (buffer.isReadable()) {
            byte b = buffer.readByte();
            System.out.print((char) b + " ");  // l o v e
        }
        System.out.println("\n\n读取完成后:");
        printBuffer(buffer);
        // 输出: readerIndex=4, writerIndex=4, capacity=10
        
        // 4. 丢弃已读数据
        buffer.discardReadBytes();
        System.out.println("\ndiscardReadBytes 后:");
        printBuffer(buffer);
        // 输出: readerIndex=0, writerIndex=0, capacity=10
        
        // 5. 清空缓冲区
        buffer.clear();
        System.out.println("\nclear 后:");
        printBuffer(buffer);
        // 输出: readerIndex=0, writerIndex=0, capacity=10
    }
    
    private static void printBuffer(ByteBuf buffer) {
        System.out.println("readerIndex: " + buffer.readerIndex());
        System.out.println("writerIndex: " + buffer.writerIndex());
        System.out.println("capacity: " + buffer.capacity());
        System.out.println("readableBytes: " + buffer.readableBytes());
        System.out.println("writableBytes: " + buffer.writableBytes());
    }
}

5.2 常用方法示例

public class ByteBufMethodsDemo {
    public static void main(String[] args) {
        ByteBuf buffer = Unpooled.buffer(10);
        
        // 写入方法
        buffer.writeByte(65);              // 写入单字节 'A'
        buffer.writeInt(100);              // 写入 int (4字节)
        buffer.writeBytes("Hi".getBytes()); // 写入字节数组
        
        // 查询方法
        int readable = buffer.readableBytes();  // 可读字节数
        int writable = buffer.writableBytes();  // 可写字节数
        boolean canRead = buffer.isReadable();  // 是否可读
        boolean canWrite = buffer.isWritable(); // 是否可写
        
        // 读取方法
        byte b = buffer.readByte();        // 读取单字节
        int i = buffer.readInt();          // 读取 int
        byte[] data = new byte[2];
        buffer.readBytes(data);            // 读取到数组
        
        // 标记和重置
        buffer.markReaderIndex();          // 标记读位置
        buffer.readByte();
        buffer.resetReaderIndex();         // 重置到标记位置
        
        buffer.markWriterIndex();          // 标记写位置
        buffer.writeByte(66);
        buffer.resetWriterIndex();         // 重置到标记位置
        
        // 跳过字节
        buffer.skipBytes(2);               // 跳过2个字节
        
        // 释放资源
        buffer.release();                  // 引用计数-1
    }
}

六、ByteBuf 三种模式

6.1 堆缓冲区(Heap Buffer)

特点:数据存储在 JVM 堆内存中

public class HeapBufferDemo {
    public static void main(String[] args) {
        // 创建堆缓冲区
        ByteBuf buffer = Unpooled.buffer(10);
        buffer.writeBytes("netty".getBytes());
        
        // 检查是否有支撑数组
        if (buffer.hasArray()) {
            byte[] array = buffer.array();  // 获取底层数组
            int offset = buffer.arrayOffset() + buffer.readerIndex();
            int length = buffer.readableBytes();
            
            System.out.println("底层数组: " + new String(array, offset, length));
            // 输出: netty
        }
    }
}

优点:

  • 快速分配和释放
  • 可直接访问底层数组

缺点:

  • Socket IO 时需要复制到直接内存

适用场景:后端业务逻辑、编解码

6.2 直接缓冲区(Direct Buffer)

特点:数据存储在堆外直接内存

public class DirectBufferDemo {
    public static void main(String[] args) {
        // 创建直接缓冲区
        ByteBuf buffer = Unpooled.directBuffer(10);
        buffer.writeBytes("netty".getBytes());
        
        // 直接缓冲区没有支撑数组
        if (!buffer.hasArray()) {
            int length = buffer.readableBytes();
            byte[] array = new byte[length];
            buffer.getBytes(buffer.readerIndex(), array);
            
            System.out.println("数据: " + new String(array));
            // 输出: netty
        }
    }
}

优点:

  • Socket IO 性能高,无需复制
  • 避免 GC 压力

缺点:

  • 分配和释放成本高
  • 不能直接访问底层数组

适用场景:网络 IO、大量数据传输

6.3 复合缓冲区(Composite Buffer)

特点:多个 ByteBuf 的逻辑视图,零拷贝

public class CompositeBufferDemo {
    public static void main(String[] args) {
        // 创建堆缓冲区
        ByteBuf heapBuf = Unpooled.buffer(3);
        heapBuf.writeBytes("net".getBytes());
        
        // 创建直接缓冲区
        ByteBuf directBuf = Unpooled.directBuffer(2);
        directBuf.writeBytes("ty".getBytes());
        
        // 创建复合缓冲区(零拷贝)
        CompositeByteBuf compositeBuf = Unpooled.compositeBuffer();
        compositeBuf.addComponents(true, heapBuf, directBuf);
        
        // 遍历所有组件
        for (ByteBuf buf : compositeBuf) {
            int length = buf.readableBytes();
            byte[] array = new byte[length];
            buf.getBytes(buf.readerIndex(), array);
            System.out.print(new String(array));  // netty
        }
        
        System.out.println("\n总可读字节: " + compositeBuf.readableBytes());
        // 输出: 5
    }
}

优点:

  • 零拷贝组合多个缓冲区
  • 避免内存复制和分配

缺点:

  • 不支持直接访问支撑数组
  • 需要先复制到堆内存

适用场景:HTTP 消息聚合、协议组装


七、ByteBuf 高级特性

7.1 自动扩容

ByteBuf buffer = Unpooled.buffer(4);  // 初始容量 4
buffer.writeBytes("Hello World".getBytes());  // 写入 11 字节
// ✅ 自动扩容,无需手动处理
System.out.println("capacity: " + buffer.capacity());  // > 11

7.2 引用计数

ByteBuf buffer = Unpooled.buffer(10);
System.out.println("refCnt: " + buffer.refCnt());  // 1

buffer.retain();  // 引用计数 +1
System.out.println("refCnt: " + buffer.refCnt());  // 2

buffer.release();  // 引用计数 -1
System.out.println("refCnt: " + buffer.refCnt());  // 1

buffer.release();  // 引用计数 -1,释放内存
// buffer 已释放,不能再使用

7.3 零拷贝

// slice() - 切片,共享底层数据
ByteBuf buffer = Unpooled.buffer(10);
buffer.writeBytes("0123456789".getBytes());

ByteBuf slice = buffer.slice(0, 5);  // 切片 [0,5)
System.out.println(slice.toString(CharsetUtil.UTF_8));  // 01234
// ✅ 零拷贝,共享底层数据

// duplicate() - 复制,共享底层数据
ByteBuf duplicate = buffer.duplicate();
// ✅ 零拷贝,独立的读写索引

// copy() - 深拷贝,独立数据
ByteBuf copy = buffer.copy();
// ⚠️ 有拷贝,独立的数据和索引

八、实战:Netty 中的使用

8.1 ChannelHandler 中使用

public class MyHandler extends ChannelInboundHandlerAdapter {
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf buf = (ByteBuf) msg;
        
        try {
            // 读取数据
            int readableBytes = buf.readableBytes();
            byte[] data = new byte[readableBytes];
            buf.readBytes(data);
            
            System.out.println("收到: " + new String(data));
            
            // 写回响应
            ByteBuf response = Unpooled.copiedBuffer("OK", CharsetUtil.UTF_8);
            ctx.writeAndFlush(response);
            
        } finally {
            // ⚠️ 重要:释放资源
            buf.release();
        }
    }
}

8.2 编解码器中使用

public class MyDecoder extends ByteToMessageDecoder {
    
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        // 检查是否有足够的数据
        if (in.readableBytes() < 4) {
            return;  // 等待更多数据
        }
        
        // 标记读位置
        in.markReaderIndex();
        
        // 读取消息长度
        int length = in.readInt();
        
        // 检查是否有完整消息
        if (in.readableBytes() < length) {
            in.resetReaderIndex();  // 重置,等待完整消息
            return;
        }
        
        // 读取消息体
        byte[] body = new byte[length];
        in.readBytes(body);
        
        // 输出解码后的消息
        out.add(new String(body));
    }
}

九、核心要点总结

9.1 ByteBuf vs ByteBuffer

特性ByteBufferByteBuf
读写指针单指针 position双指针 readerIndex/writerIndex
模式切换需要 flip()无需切换
容量固定可自动扩容
内存管理JVM GC引用计数
零拷贝不支持支持 slice/duplicate
API复杂简洁友好

9.2 使用建议

  1. 选择合适的模式:

    • 网络 IO → 直接缓冲区
    • 业务逻辑 → 堆缓冲区
    • 消息组装 → 复合缓冲区
  2. 注意内存释放:

    • 使用完毕后调用 release()
    • 或使用 try-finally 确保释放
  3. 善用零拷贝:

    • 使用 slice() 切片
    • 使用 CompositeByteBuf 组合
  4. 标记和重置:

    • 使用 mark/reset 实现回退
    • 避免重复读取

十、常见问题

Q1: 什么时候需要 release()?

A: 当你是 ByteBuf 的最后一个使用者时。

// 场景1: ChannelHandler 中
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    ByteBuf buf = (ByteBuf) msg;
    try {
        // 处理数据
    } finally {
        buf.release();  // ✅ 必须释放
    }
}

// 场景2: 传递给下一个 Handler
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    ctx.fireChannelRead(msg);  // ✅ 无需释放,由下一个 Handler 负责
}

Q2: readBytes() 和 getBytes() 的区别?

A:

  • readBytes(): 移动 readerIndex
  • getBytes(): 不移动 readerIndex
ByteBuf buf = Unpooled.copiedBuffer("ABCD", CharsetUtil.UTF_8);

byte[] data1 = new byte[2];
buf.readBytes(data1);  // 读取 AB,readerIndex 移动到 2

byte[] data2 = new byte[2];
buf.getBytes(0, data2);  // 读取 AB,readerIndex 不变

Q3: 如何避免内存泄漏?

A:

  1. 使用 try-finally 确保释放
  2. 使用 Netty 的 ResourceLeakDetector 检测泄漏
  3. 遵循"谁创建谁释放"原则
// 启用泄漏检测
-Dio.netty.leakDetection.level=PARANOID

下一步:学习 Netty 的编解码器框架

【Netty系列10】Netty源码探秘:核心机制解析 本文深入解析Netty框架的两大核心机制:EventLoop运行流程和ByteBuf池化分配。EventLoop采用单线程串行处理模式,通过任务队列、IO事件监听和任务执行的循环实现高效事件处理。ByteBuf池化分配通过分级内存块、引用计数和本地线程缓存实现零拷贝和内存复用,显著提升性能。文章结合源码剖析设计思想,揭示Netty如何通过事件循环调度与内存池化实现高并发与低GC开销的平衡,为构建高性能网络应用提供经典范本。 阅读详情

相关推荐

Netty的ByteBuf相比JDK的ByteBuffer有什么优势?

痛点1:固定容量困境// ByteBuffer的典型创建方式// 容量固定为1024字节// 当需要写入超过1024字节的数据时,必须手动处理// 缓冲区已满,必须执行IO操作刷新数据// 重置缓冲区状态这种固定容量设计在处理动态大小数据时极为不便,迫使开发者编写复杂的分块逻辑,增加了代码复杂度和出错风险。痛点2:位置指针管理的复杂性ByteBuffer使用单一position指针跟踪当前操作位置,读写切换时必须手动调用flip()rewind()或clear()

AI天才研究院 1143

【Netty源码解读和权威指南】第11篇:Netty ByteBuf全解析(上)—— 告别NIO ByteBuffer的痛,Netty缓冲区就是这么香

本文深入解析了Netty ByteBuf缓冲区相比NIO ByteBuffer的显著优势。首先通过一个线上事故案例,揭示了NIO ByteBuffer读写指针共用、状态切换繁琐等"七宗罪"。然后详细对比了ByteBuf的核心改进:读写指针分离设计、自动扩容机制和丰富API。通过代码示例展示了ByteBuf的创建、读写操作,突出其无需flip()切换的便捷性。文章采用技术对比和实际案例相结合的方式,帮助开发者理解ByteBuf的设计哲学和正确使用方法。

xyghehehehe的专栏 361

手把手调试:如何为高通Hypervisor上的GuestOS添加一个自定义的HAB服务通道

本文详细介绍了如何在高通Hypervisor环境下为GuestOS添加自定义HAB服务通道的全过程。从HAB通信框架的核心概念解析到设备树节点的动态注入机制,再到物理通道的内核层实现和用户层测试,提供了完整的开发案例和调试技巧,帮助开发者高效构建定制化通信服务。

weixin_27066963的博客 371

Netty源码分析-缓冲区Buffer体系结构设计

概念 Netty的缓冲区Buffer是一个与Netty框架相对独立的模块,在Java NIO中使用ByteBuffer作为缓冲区实现,但是ByteBuffer是使用单指针position来控制对缓冲区的读写操作的,在读写之间需用通过flip函数来切换position指针,若忘记调用flip,则可能在写了之后读不出来,用法比较繁琐,而且容易出错,关于Java NIO的设计,可以参考我的另外一篇文章...

源码之下,了无秘密 4989

告别UI字体臃肿!详解TextMeshPro字体AssetBundle打包优化技巧(Unity 2022实测)

本文详细解析了Unity 2022中使用TextMeshPro时字体资源AssetBundle打包的优化技巧,特别针对中日文等多语言场景下的字体臃肿问题。通过公共资源标记、依赖关系分析和实战案例,帮助开发者有效减少包体体积和内存占用,提升游戏性能。

weixin_33725722的博客 420

python模拟银行交易流水

模拟自动生成银行交易流水,其中包括:入账账号、出账账号、交易金额、交易余额、交易时间、出入表示关键字段

qq_31823889的博客 2910

Netty 源码分析04 Buffer01

1. 概述 一个 Buffer ,本质上是内存中的一块,我们可以将数据写入这块内存,之后从这块内存获取数据。通过将这块内存封装成 NIO Buffer 对象,并提供了一组常用的方法,方便我们对该块内存的读写。 Buffer 在java.nio包中实现,被定义成抽象类,从而实现一组常用的方法。整体类图如下: 我们可以将 Buffer 理解为一个数组的封装,例如 IntBuffer、Ch...

郭传志的博客 223

Vivado实战:从零封装AXI-Lite接口的呼吸灯IP核

本文提供了一份详细的Vivado实战指南,手把手教你如何将Verilog编写的呼吸灯模块封装成带AXI-Lite接口的IP核。内容涵盖从创建IP框架、编写核心逻辑、连接AXI总线到在ZYNQ系统中调用并编写C程序进行软硬件协同测试的完整流程,是掌握FPGA软硬件协同设计的关键实践。

weixin_29233333的博客 598

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

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

惜暮 3万+

(04730)半导体器件之基本放大器工作原理(一)

放大器是构成各种电子线路的基本单元电路。所谓“放大”,就是将输入的微弱信号(微弱变化的电压或电流等)去控制直流电源提供的能量,并使输出按照输入的小信号变化规律而变化的过程。所以放大器的本质是能量转换器。本节重点学习基本放大电路的工作原理和基本分析方法及主要性能指标。

黄先生的博客 3008

[QMT量化交易小白入门]-104、QMT平台运行深度学习模型,预测期货价格

本专栏主要是介绍QMT的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写100篇左右。QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。

木头大左的博客 486

18.Netty源码之ByteBuf 详解

highlight: arduino-light ByteBuf 是 Netty 的数据容器,所有网络通信中字节流的传输都是通过 ByteBuf 完成的。 然而 JDK NIO 包中已经提供了类似的 ByteBuffer 类,为什么 Netty 还要去重复造轮子呢?本节课我会详细地讲解 ByteBuf。 JDK NIO的ByteBuffer 我们首先介绍下 JDK NIO 的 Byte...

qq_30635523的博客 2193

CloudCompare源码分析之CCCoreLib模块:ICP算法(阅读经典)

CloudCompare源码分析之CCCoreLib模块:ICP算法(阅读经典)

dayuhaitang1的博客 2551

Netty源码分析之ByteBuf

一、Java中的Buffer对象 我们知道Buffer是NIO底层的重要组件之一,netty沿用了NIO中的Buffer实现,并且进行了更进一步的封装,所以我们先来了解一下NIO中的Buffer。 Buffer中有三个非常重要的属性,源码中的注解是这样描述的: capacity:表示一个buffer的容量,这个值一旦确定就不会被改变,类似于一位数组,数组长度一旦确认就不会在变。 limit:表示,第一个元素不能被读或写的索引,并且不能大于capacity。 position:是下一个能被读或写的元素索引。p

solayang的博客 447

Freeswitch DTMF 按键无法接收问题修复

freeswitch 在接收到 update后,会更新成新的 payload type,但是给的200响应,仍然是旧的,这时候就会导致手机侧认识需要发送旧的payload,所以发到 fs 后就会导致直接丢包,不去处理RTP包了。呼叫时需要设置通道变量 rtp_manual_rtp_bugs=ACCEPT_ANY_PAYLOAD ,这时候FS 就不会对包的payload进行判断,直接判定通过。应该修复 freeswitch 给响应时,应该根据收到的 payload 发送给手机,但是一直未找到正确的路径。

2301_81507069的博客 374

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Netty 源码分析系列(七)字节缓冲区 ByteBuf(下)

在了解了 ByteBuffer 的原理之后,再来理解 Netty 的 ByteBuf 就比较简单了。ByteBuf 是 Netty 框架封装的数据缓冲区,区别于positionlimitflip等属性和操作来控制ByteBuffer的读写,ByteBuf通过两个位置指针来协助缓冲区的读写操作,分别是readIndex和writeIndex。readIndexwriteIndex和capacity通过以上对于ByteBuf的介绍,相信小伙伴们对于ByteBuf的原理也有了一定的了解。

初念初恋的博客 1107

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Netty5源码分析(五) -- ByteBuf缓冲区

Netty的ByteBuf缓冲区实现地比Java本身的ByteBuffer更加灵活,方便。它的类结构也比较复杂,这里只说ByteBuf核心的几个要点。 1. 最重要的是要理解为什么要ByteBuf这个组件。主要还是因为基于select / poll / epoll这种IO多路复用技术的NIO是非阻塞同步IO的模型,由于是同步IO,需要用户线程自己来处理IO的读写,由于是非阻塞的,每次调用

ITer_ZC的专栏 5749

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

记录一下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

bytebuf池_Netty默认的Bytebuf是堆内还是堆外?池化or非池化?

开篇Netty的ByteBuf有从不同角度有如下2个分类,4种组合!堆外内存和堆内内存池化和非池化我们在利用Netty做底层通信框架的时候,会默认给我们的到底是哪一种组合了?分析池化分析Netty的Boostrap启动类按照标准模板,通常会添加这个配置option(ChannelOption.ALLOCATOR, ByteBufAllocator.DEFAULT)val serverBootstr...

weixin_31534091的博客 758

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

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

xianghe_qqq的博客 1117

Netty 源码分析系列(十三)Netty 编码器

上一篇我们讲解了解码器的相关知识,其中也提到了编码器的定义。编码器就是用来把出站数据从一种格式转换到另外一种格式,因此它实现了编码从消息到字节(编码从消息到消息(通过上述文章的讲解,我们对于编码器和解码器应该都有了一定的认识,其实针对编码和解码,Netty 还提供了第三种方式,那就是编解码器。

初念初恋的博客 706

Netty学习笔记九:netty源码分析和设计模式

1. Netty学习笔记九:netty源码分析和设计模式 文章目录1. Netty学习笔记九:netty源码分析和设计模式1.1. Netty核心模块缓冲ByteBuf1.2. ByteBuf的创建方法1.3. ByteBuf使用模式2. Netty里面的设计模式应用分析2.1. Builder构造器模式2.2. 责任链设计模式2.3. 工厂设计模式2.4. 适配器模式2.5. 设计模式推荐书籍 ...

公子&小白的博客 745

Netty 高性能的秘密:ByteBuf 与零拷贝机制

JDK 的 ByteBuffer 存在容量固定、API 繁琐的问题。Netty 的 ByteBuf 提供了动态扩容、读写指针分离、内存池化。零拷贝机制(Slice、CompositeBuffer、FileRegion)大幅减少内存复制开销。这是 Netty 性能远超 JDK NIO 的重要原因之一。👉 下一篇,我们将进入Netty 实战篇,看看它是如何在 RPC 框架、即时通讯、WebSocket 等场景中大显身手的。

波波烤鸭的博客 1099

Netty核心组件与源码分析

Netty核心组件与源码分析

paopaodog的博客 490

Netty核心线程模型

Netty线程模型图Netty线程模型源码图Netty高并发高性能架构设计精髓无锁串行化设计思想直接内存直接内存与堆内存的区别直接内存分配源码分析:使用直接内存的优缺点:Netty零拷贝ByteBuf内存池设计灵活的TCP参数配置能力并发优化ByteBuf扩容机制在大多数场景下,并行多线程处理可以提升系统的并发性能。但是,如果对于共享资源的并发访问处理不当,会带来严重的锁竞争,这最终会导致性能的下降。为了尽可能的避免锁竞争带来的性能损耗,可以通过串行化设计,即消息的处理尽可能在同一个线程内完成,期间不进

qq_45061342的博客 1742

四、Netty核心源码剖析

目录 为什么要看源码: 一、Netty线程模型图 1.1 Netty线程模型源码剖析图 二、Netty高并发高性能架构设计精髓 2.1 无锁串行化设计思想 2.2 直接内存 2.3 直接内存分配源码分析: 2.3.1 使用直接内存的优缺点: 2.4 Netty零拷贝 2.5 ByteBuf内存池设计 2.6 灵活的TCP参数配置能力 2.7 ByteBuf扩容机制 2.8补充:handler的生命周期回调接口调用顺序 为什么要看源码: 提升技术功底:学习源码里的优秀设计..

Xx__WangQi的博客 728
上一篇: Netty源码分析---Java-NIO-ByteBuffer核心详解-简化版
下一篇: Netty源码分析---Netty-Pipeline初始化流程详解
不早睡不改名@
博客等级 码龄5年 536粉丝 306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值