Netty入门——ByteBuf

Posted 小志的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty入门——ByteBuf相关的知识,希望对你有一定的参考价值。

目录

一、ByteBuf的概述

  • ByteBuf是对字节数据的封装。

二、ByteBuf的创建

2.1、创建一个带有初始容量的ByteBuf代码示例

  • 代码示例

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.ByteBufAllocator;
    import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
    import static io.netty.util.internal.StringUtil.NEWLINE;
    /**
     * @description: ByteBuf(创建)
     * @author: xz
     */
    public class ByteBufTest 
        public static void main(String[] args) 
            //createByteBuf1();
        
    
        /**
         *  创建了一个初始容量是 10 的ByteBuf
         * */
        public static void createByteBuf1()
            //创建了一个默认的 ByteBuf(池化基于直接内存的 ByteBuf),初始容量是 10
            ByteBuf buf = ByteBufAllocator.DEFAULT.buffer(10);
            System.out.println("查看设置的ByteBuf初始容量:"+buf);
        
        /**
         * 输出ByteBuf的工具类
         * */
        public static void log(ByteBuf buffer) 
            int length = buffer.readableBytes();
            int rows = length / 16 + (length % 15 == 0 ? 0 : 1) + 4;
            StringBuilder buf = new StringBuilder(rows * 80 * 2)
                    .append("read index:").append(buffer.readerIndex())
                    .append(" write index:").append(buffer.writerIndex())
                    .append(" capacity:").append(buffer.capacity())
                    .append(NEWLINE);
            appendPrettyHexDump(buf, buffer);
            System.out.println(buf.toString());
        
    
    
  • 输出结果

2.2、查看ByteBuf最大容量的代码示例

  • 代码示例

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.ByteBufAllocator;
    import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
    import static io.netty.util.internal.StringUtil.NEWLINE;
    /**
     * @description: ByteBuf(创建)
     * @author: xz
     */
    public class ByteBufTest 
        public static void main(String[] args) 
            createByteBuf2();
        
         /**
         *  查看ByteBuf最大容量
         * */
        public static void createByteBuf2()
            //创建了一个默认的 ByteBuf(池化基于直接内存的 ByteBuf)
            ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
            //查看ByteBuf最大容量
            System.out.println("ByteBuf最大容量:"+buf.maxCapacity());
        
        /**
         * 输出ByteBuf的工具类
         * */
        public static void log(ByteBuf buffer) 
            int length = buffer.readableBytes();
            int rows = length / 16 + (length % 15 == 0 ? 0 : 1) + 4;
            StringBuilder buf = new StringBuilder(rows * 80 * 2)
                    .append("read index:").append(buffer.readerIndex())
                    .append(" write index:").append(buffer.writerIndex())
                    .append(" capacity:").append(buffer.capacity())
                    .append(NEWLINE);
            appendPrettyHexDump(buf, buffer);
            System.out.println(buf.toString());
        
    
    
  • 输出结果

2.3、查看ByteBuf最大容量及扩容后最大容量的代码示例

  • 代码示例

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.ByteBufAllocator;
    import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
    import static io.netty.util.internal.StringUtil.NEWLINE;
    
    /**
     * @description: ByteBuf(创建)
     * @author: xz
     */
    public class ByteBufTest 
        public static void main(String[] args) 
            createByteBuf3();
        
         /**
         *  查看ByteBuf最大容量及扩容后的最大容量
         * */
        public static void createByteBuf3()
            //1、创建了一个默认的 ByteBuf(池化基于直接内存的 ByteBuf),最大容量256
            ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
            //调用输出ByteBuf的工具类
            log(buf);
    
            //2、创建长度为300的字符串写入ByteBuf,查看扩容后的最大容量
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 300; i++) 
                sb.append("a");
            
            buf.writeBytes(sb.toString().getBytes());
            //调用输出ByteBuf的工具类
            log(buf);
        
        /**
         * 输出ByteBuf的工具类
         * */
        public static void log(ByteBuf buffer) 
            int length = buffer.readableBytes();
            int rows = length / 16 + (length % 15 == 0 ? 0 : 1) + 4;
            StringBuilder buf = new StringBuilder(rows * 80 * 2)
                    .append("read index:").append(buffer.readerIndex())
                    .append(" write index:").append(buffer.writerIndex())
                    .append(" capacity:").append(buffer.capacity())
                    .append(NEWLINE);
            appendPrettyHexDump(buf, buffer);
            System.out.println(buf.toString());
        
    
    
  • 输出结果

三、ByteBuf (直接内存 vs 堆内存)

3.1、创建池化基于堆的ByteBuf 代码示例

  • 代码示例

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.ByteBufAllocator;
    import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
    import static io.netty.util.internal.StringUtil.NEWLINE;
    /**
     * @description: ByteBuf (直接内存 vs 堆内存)
     * @author: xz
     */
    public class ByteBufTest2 
        public static void main(String[] args) 
            //创建了一个默认的 ByteBuf(创建池化基于堆的 ByteBuf),初始容量是 10
            ByteBuf buf1 = ByteBufAllocator.DEFAULT.heapBuffer(10);
            //通过输出类信息PooledUnsafeHeapByteBuf可知,采用的是池化基于堆内存
            System.out.println(buf1.getClass());//输出class io.netty.buffer.PooledUnsafeHeapByteBuf
            //输出容量
            log(buf1);
        
    
        /**
         * 输出ByteBuf的工具类
         * */
        public static void log(ByteBuf buffer) 
            int length = buffer.readableBytes();
            int rows = length / 16 + (length % 15 == 0 ? 0 : 1) + 4;
            StringBuilder buf = new StringBuilder(rows * 80 * 2)
                    .append("read index:").append(buffer.readerIndex())
                    .append(" write index:").append(buffer.writerIndex())
                    .append(" capacity:").append(buffer.capacity())
                    .append(NEWLINE);
            appendPrettyHexDump(buf, buffer);
            System.out.println(buf.toString());
        
    
    
  • 输出结果

3.2、创建池化基于直接内存的ByteBuf 代码示例

  • 代码示例

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.ByteBufAllocator;
    import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
    import static io.netty.util.internal.StringUtil.NEWLINE;
    /**
     * @description: ByteBuf (直接内存 vs 堆内存)
     * @author: xz
     */
    public class ByteBufTest2 
        public static void main(String[] args) 
            //创建了一个默认的 ByteBuf(创建池化基于直接内存的 ByteBuf),初始容量是 10
            ByteBuf buf2 = ByteBufAllocator.DEFAULT.directBuffer(10);
            //通过输出类信息PooledUnsafeDirectByteBuf可知,采用的是池化基于直接内存
            System.out.println(buf2.getClass());//输出class io.netty.buffer.PooledUnsafeDirectByteBuf
            //输出容量
            log(buf2);
        
    
        /**
         * 输出ByteBuf的工具类
         * */
        public static void log(ByteBuf buffer) 
            int length = buffer.readableBytes();
            int rows = length / 16 + (length % 15 == 0 ? 0 : 1) + 4;
            StringBuilder buf = new StringBuilder(rows * 80 * 2)
                    .append("read index:").append(buffer.readerIndex())
                    .append(" write index:").append(buffer.writerIndex())
                    .append(" capacity:").append(buffer.capacity())
                    .append(NEWLINE);
            appendPrettyHexDump(buf, buffer);
            System.out.println(buf.toString());
        
    
    
  • 输出结果

四、ByteBuf (池化 vs 非池化)

4.1、默认采用的是池化基于直接内存的 代码示例

  • 代码示例

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.ByteBufAllocator;
    /**
     * @description: ByteBuf (池化 vs 非池化)
     * @author: xz
     */
    public class ByteBufTest3 
        public static void main(String[] args) 
            getPooledByteBuf();
        
        /**
         * 默认采用的是池化基于直接内存
         * */
        public static void getPooledByteBuf()
            //创建了一个默认的 ByteBuf(创建池化基于直接内存的 ByteBuf)
            ByteBuf buf1 = ByteBufAllocator.DEFAULT.buffer();
            //通过输出类信息PooledUnsafeDirectByteBuf可知,采用的是池化基于直接内存
            System.out.println(buf1.getClass());//输出class io.netty.buffer.PooledUnsafeDirectByteBuf
        
    
    
  • 输出结果

4.1、设置vm参数采用非池化基于直接内存的 代码示例

  • 代码示例

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.ByteBufAllocator;
    /**
     * @description: ByteBuf (池化 vs 非池化)
     * @author: xz
     */
    public class ByteBufTest3 
        public static void main(String[] args) 
            getUnPooledByteBuf();
        
    
        /**
         * 通过设置vm参数 -Dio.netty.allocator.type=unpooled之后,
         * 采用的是非池化基于直接内存
         * */
        public static void getUnPooledByteBuf()
            //创建了一个默认的 ByteBuf(创建非池化基于直接内存的 ByteBuf)
            ByteBuf buf1 = ByteBufAllocator.DEFAULT.buffer();
            //通过输出类信息UnpooledByteBufAllocator可知,采用的是非池化基于直接内存
            System.out.println(buf1.getClass());//输出class io.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf
        
    
    
  • 通过设置vm参数 -Dio.netty.allocator.type=unpooled之后,采用非池化基于直接内存。

  • 输出结果

五、ByteBuf 组成

  • ByteBuf 由四部分组成,最开始读写指针都在 0 位置。

六、ByteBuf 写入

6.1、ByteBuf 写入方法

  • ByteBuf 写入方法列表,省略一些不重要的方法

    方法签名含义备注
    writeBoolean(boolean value)写入 boolean 值用一字节 01|00 代表 true|false
    writeByte(int value)写入 byte 值
    writeShort(int value)写入 short 值
    writeInt(int value)写入 int 值Big Endian,即 0x250,写入后 00 00 02 50,先写高位在写低位
    writeIntLE(int value)写入 int 值Little Endian,即 0x250,写入后 50 02 00 00,先写低位在写高位
    writeLong(long value)写入 long 值
    writeChar(int value)写入 char 值
    writeFloat(float value)写入 float 值
    writeDouble(double value)写入 double 值
    writeBytes(ByteBuf src)写入 netty 的 ByteBuf
    writeBytes(byte[] src)写入 byte[]
    writeBytes(ByteBuffer src)写入 nio 的 ByteBuffer
    int writeCharSequence(CharSequence sequence, Charset charset)写入字符串

6.2、ByteBuf 写入的 代码示例

  • 代码示例

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.ByteBufAllocator;
    import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
    import static io.netty.util.internal.StringUtil.NEWLINE;
    /**
     * @description: ByteBuf (写入)
     * @author: xz
     */
    public class ByteBufTest4 
        public static void main(String[] args) 
            getWriteBytes();
        
        public static void getWriteBytes()
            //创建了一个默认的 ByteBuf(池化基于直接内存的 ByteBuf),初始容量是 10
            ByteBuf buf1 = ByteBufAllocator.DEFAULT.buffer(10);
            //1、先写入 4 个字节
            buf1.writeBytes(new byte[]1, 2, 3, 4);
            log(buf1);
            //2、再写入一个 int 整数,也是 4 个字节
            buf1.writeInt(5);
            log(buf1);
        
    
        /**
         * 输出ByteBuf的工具类
         * */
        public static void log(ByteBuf buffer) 
            int length = buffer.readableBytes();
            int rows 以上是关于Netty入门——ByteBuf的主要内容,如果未能解决你的问题,请参考以下文章

    netty4.x ByteBuf 基本机制及其骨架实现

    Netty系列之:netty中的ByteBuf详解

    netty里的ByteBuf扩容源码分析

    Netty之ByteBuf原理解析及应用

    Netty OOM案例

    netty ByteBuf