Netty-ByteBuf 详解

Java 中基本类型所占的字节数

byte     1字节               
short    2字节               
int      4字节               
long     8字节               
char     2字节 可以存储一个汉字
float    4字节               
double   8字节  
getXXX setXXX不改变指针的操作

public class ByteBufTest002 {
    public static void main(String[] args) {
        ByteBuf byteBuf  = Unpooled.copiedBuffer("ABCDEFH", CharsetUtil.UTF_8);
        System.out.println(byteBuf.writerIndex());
        for (int i  = 0; i < byteBuf.writerIndex() ; i++){
            byte b = byteBuf.getByte(i);
            System.out.println((char)b + "---------" + byteBuf.readerIndex());
        }
        System.out.println();

        for (int i = 0 ; i < byteBuf.writerIndex(); i++){
            byteBuf.setByte(1,'l');
            System.out.println(byteBuf.writerIndex());
        }
    }
}

执行结果

7
A---------0
B---------0
C---------0
D---------0
E---------0
F---------0
H---------0

7
7
7
7
7
7
7

结论:

get跟set开头的方法不会改变readerIndex 跟 writerIndex

Buffer中的指针变量跟区域

discardable 被读过的废弃掉的

 * <pre>
 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      |                   |     (CONTENT)    |                  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 * </pre>

可读字节

public class ByteBufTest003 {
    public static void main(String[] args) {
        ByteBuf byteBuf  = Unpooled.copiedBuffer("ABCDEFH", CharsetUtil.UTF_8);
        
        //可读的字节
        while (byteBuf.isReadable()){
            System.out.println((char) byteBuf.readByte() + " ====== " +byteBuf.readerIndex());
        }

        //已经读完了再读就会发生异常
        byteBuf.readByte();
    }
}

执行结果

A ====== 1
B ====== 2
C ====== 3
D ====== 4
E ====== 5
F ====== 6
H ====== 7
Exception in thread "main" java.lang.IndexOutOfBoundsException: readerIndex(7) + length(1) exceeds writerIndex(7): UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(ridx: 7, widx: 7, cap: 21)
	at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1495)
	at io.netty.buffer.AbstractByteBuf.readByte(AbstractByteBuf.java:745)
	at com.clown.netty.bytebuftest.ByteBufTest003.main(ByteBufTest003.java:16)

总结 wirteXXX,readXXX 会改变readerIndex 跟 writerIndex。

可写字节

/**
 * 可写字节
 */
public class ByteBufTest004 {
    public static void main(String[] args) {
        ByteBuf byteBuf  = Unpooled.copiedBuffer("ABCDEFH", CharsetUtil.UTF_8);
        SecureRandom random = new SecureRandom();
        System.out.println("capacity is" + byteBuf.capacity());
        while (byteBuf.writableBytes() > 0 ){
            byteBuf.writeByte(random.nextInt());
            System.out.println(byteBuf.writerIndex());
        }
    }
}
ByteBufAllocator
  1. 获得ByteBufAllocator
        //通过ChannelHandlerContext
        ByteBufAllocator allocator = channelHandlerContext.alloc();
        ByteBuf buffer = allocator.buffer(16, 32);

        //通过Channel
        ByteBufAllocator allocator1 =  channelHandlerContext.channel().alloc();
        ByteBuf byteBuf2 = allocator1.buffer(32);
        
        //创建DirectByteBuf
        ByteBuf directByteBuf = allocator1.directBuffer(16);

Netty提供了两种ByteBufAllocator的实现:PooledByteBufAllocator和Unpooled-ByteBufAllocator。前者池化了ByteBuf的实例以提高性能并最大限度地减少内存碎片。

此实现使用了一种称为jemalloc的已被大量现代操作系统所采用的高效方法来分配内存,后面是每次都创建一个新的。

虽然Netty默认使用了PooledByteBufAllocator,但这可以很容易地通过Channel-ConfigAPI或者在引导你的应用程序时指定一个不同的分配器来更改。

UnpooledBuffer

名称描述
buffer(),
buffer(int capacity),
buffer(int capacity,int maxCapacity)
返回一个未池化得基于堆存储得ByteBuf
directBuffer()
directBuffer(int initialCapacity)
directBuffer(int initialCapacity, int maxCapacity)
返回一个未被池化的ByteBuf
wrappedBuffer()返回一个包装了给定数据的ByteBuf
copiedBuffer()返回一个复制了给定数据的ByteBuf

clear() 方法 readerIndex 跟writeIndex 都等于 0

 * <pre>
 *  BEFORE clear()
 *
 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 *
 *
 *  AFTER clear()
 *
 *      +---------------------------------------------------------+
 *      |             writable bytes (got more space)             |
 *      +---------------------------------------------------------+
 *      |                                                         |
 *      0 = readerIndex = writerIndex            <=            capacity
 * </pre>

discardReadBytes()方法对读写索引的影响

 * <pre>
 *  BEFORE discardReadBytes()
 *
 *      +-------------------+------------------+------------------+
 *      | discardable bytes |  readable bytes  |  writable bytes  |
 *      +-------------------+------------------+------------------+
 *      |                   |                  |                  |
 *      0      <=      readerIndex   <=   writerIndex    <=    capacity
 *
 *
 *  AFTER discardReadBytes()
 *
 *      +------------------+--------------------------------------+
 *      |  readable bytes  |    writable bytes (got more space)   |
 *      +------------------+--------------------------------------+
 *      |                  |                                      |
 * readerIndex (0) <= writerIndex (decreased)        <=        capacity
 * </pre>

clear() 方法比较的轻量级将两个指针都指到了零位置上。虽然discardReadBytes 也可以提供新的内存空间来往ByteBuf 来写数据,但是它会涉及到数据的复制。所以建议使用clear 方法。

ByteBuf 通过两个指针变量来维护底层读写。避免了NIO ByteBuffer的flip() 操作。 并且支持池化,减少内存碎片,也支持堆上分配,跟堆外内存两种方式,还有复合模式的支持。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值