Java io.netty.buffer.ByteBuf

ByteBuf 与 ByteBuffer 核心区别:Netty 对 JDK NIO 的优化升级
io.netty.buffer.ByteBuf 是 Netty 基于 JDK NIO 的 java.nio.ByteBuffer 设计的增强型缓冲区,核心目标是解决 ByteBuffer 的易用性、功能局限性问题,同时适配 Netty 的高性能网络编程场景。二者的本质差异体现在设计理念、易用性、功能扩展、性能优化四个维度,以下是详细对比:
一、核心区别总览表

对比维度ByteBuffer(JDK NIO)ByteBuf(Netty)
读写模式切换 需手动调用 flip()(写转读)、clear()/compact()(读转写),易出错 读写指针分离(readerIndex/writerIndex),无需切换,天然支持顺序读写
容量动态扩展 固定容量,扩容需手动创建新缓冲区并拷贝数据 支持动态扩容(默认按 2 倍增长,可自定义策略),自动处理容量不足
操作便捷性 API 繁琐(如 getInt() 需手动控制偏移量),无内置工具方法 提供丰富的读写方法(readInt()/writeInt()readBytes()/writeBytes()),支持字符串、数组、其他缓冲区直接读写
零拷贝支持 仅支持基础的 slice()/duplicate()(共享底层数据),功能有限 原生支持复合缓冲区(CompositeByteBuf)、Unpooled.wrappedBuffer() 等,彻底避免数据拷贝,提升网络传输性能
内存管理 仅支持堆内存(HeapByteBuffer)和直接内存(DirectByteBuffer),无池化机制 支持堆内存、直接内存,且内置内存池(PooledByteBuf) ,减少 GC 压力,提升高并发场景性能
索引访问 仅有一个 position 指针,读写需手动计算偏移量 支持绝对索引(getInt(int index))和相对索引(readInt()),读写互不干扰
可丢弃字节处理 需手动调用 compact() 压缩缓冲区(拷贝有效数据) 直接调用 discardReadBytes(),无需拷贝,仅调整 readerIndex,高效回收已读空间
标记与重置 仅支持一个 mark 和 reset,且受模式切换影响 支持多个标记(MarkAware),且标记与读写指针独立,不受操作影响
适用场景 基础 NIO 编程,简单缓冲区操作 Netty 网络编程、高性能 IO 场景,需频繁读写 / 扩容 / 零拷贝的场景

二、示例代码ByteBuffer

import java.nio.ByteBuffer;

public class ByteBufferDemo {
    public static void main(String[] args) {
        // 初始化容量为10的缓冲区
        ByteBuffer buf = ByteBuffer.allocate(10);
        
        // 1. 写数据:position从0→4
        buf.putInt(12345);
        System.out.println("写后position: " + buf.position()); // 输出4
        
        // 2. 必须手动flip()切换为读模式,否则读不到数据
        buf.flip();
        System.out.println("flip后position: " + buf.position()); // 输出0
        
        // 3. 读数据:position从0→4
        int value = buf.getInt();
        System.out.println("读取的值: " + value); // 输出12345
        
        // 4. 读完要重新写,需手动clear()
        buf.clear();
    }
}

三、示例代码ByteBuf

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

public class ByteBufDemo {
    public static void main(String[] args) {
        // 初始化容量为10的缓冲区
        ByteBuf buf = Unpooled.buffer(10);
        
        // 1. 写数据:writerIndex从0→4
        buf.writeInt(12345);
        System.out.println("写后writerIndex: " + buf.writerIndex()); // 输出4
        
        // 2. 直接读,无需切换:readerIndex从0→4
        int value = buf.readInt();
        System.out.println("读取的值: " + value); // 输出12345
        
        // 3. 直接继续写,无需清空
        buf.writeLong(67890L);
    }
}

四、转十六进制输入

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

public class ByteBufHexPrint {
    public static void main(String[] args) {
        // 1. 创建一个测试用的ByteBuf并写入数据
        ByteBuf buf = Unpooled.buffer();
        // 写入一些测试数据:字符串"Netty" + 整数123
        buf.writeBytes("Netty".getBytes());
        buf.writeInt(123);

        // 2. 方式1:打印整个ByteBuf的十六进制(最常用)
        String hexStr = ByteBufUtil.hexDump(buf);
        System.out.println("完整ByteBuf的十六进制:");
        System.out.println(hexStr); // 输出:4e657474790000007b

        // 3. 方式2:打印指定区间的十六进制(比如只打印前5个字节)
        String partialHexStr = ByteBufUtil.hexDump(buf, 0, 5);
        System.out.println("\n前5个字节的十六进制:");
        System.out.println(partialHexStr); // 输出:4e65747479(对应"Netty")

        // 4. 方式3:带格式的十六进制(每行固定长度,更易读)
        System.out.println("\n带格式的十六进制(调试友好):");
        printHexDump("测试ByteBuf", buf);
    }

    /**
     * 封装一个通用方法,打印带格式的十六进制(包含偏移量、十六进制、ASCII码)
     */
    public static void printHexDump(String title, ByteBuf buf) {
        // hexDump方法重载:支持指定标题,自动格式化输出
        System.out.println(ByteBufUtil.hexDump(title, buf));
    }
}

 

posted @ 2025-12-26 17:01  都是城市惹的祸  阅读(24)  评论(0)    收藏  举报