《跟闪电侠学Netty》阅读笔记 - 数据载体ByteBuf(二)

简介: 《跟闪电侠学Netty》阅读笔记 - 数据载体ByteBuf

《跟闪电侠学Netty》阅读笔记 - 数据载体ByteBuf(一)https://developer.aliyun.com/article/1395305

读写API

实践读写API之前,我们先构建ByteBuf。


ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(9, 100);  
print("allocate ByteBuf(9,100) => {} \n", buffer);

上面的代码

writeBytes(byte[] src) 与 buffer.readBytes(byte[] dst)

writeBytes() 表示把字节数组 src 里面的数据全部写到 ByteBuf。注意此方法执行之后,会移动前面介绍的 writeIndex 写指针。


// write 方法改变写指针  
buffer.writeBytes(new byte[]{1, 2, 3, 4});  
print("改变写指针 writeBytes(new byte[]{1,2,3,4}) => {} \n", buffer);  
// 改变写指针 writeBytes(new byte[]{1,2,3,4}) => PooledUnsafeDirectByteBuf(ridx: 0, widx: 4, cap: 9/100)

readBytes() 指的是把 ByteBuf 里面的数据全部读取到 dst。


//只有read方法改变指针  
byte[] bytes = new byte[buffer.readableBytes()];  
buffer.readBytes(bytes);  
print("bytes 内容 => {}", bytes);  
// bytes 内容 =>    

这里 dst 字节数组的大小通常等于 readableBytes(),而 src 字节数组大小的长度通常小于等于writableBytes()。

writeByte(byte b) 与 buffer.readByte()

writeByte() 表示往 ByteBuf 中写一个字节,而 buffer.readByte() 表示从 ByteBuf 中读取一个字节,类似的 API 还有 writeBoolean()、writeChar()、writeShort()、writeInt()、writeLong()、writeFloat()、writeDouble() 与 readBoolean()、readChar()、readShort()、readInt()、readLong()、readFloat()、readDouble() 这里就不一一赘述。


// write 方法改变写指针  
buffer.writeBytes(new byte[]{1, 2, 3, 4});  
print("改变写指针 writeBytes(new byte[]{1,2,3,4}) => {} \n", buffer);  
// 改变写指针 writeBytes(new byte[]{1,2,3,4}) => PooledUnsafeDirectByteBuf(ridx: 0, widx: 4, cap: 9/100)buffer.writeByte(5);  
print("改变写指针 buffer.writeByte(5) => {} \n", buffer);  
// 改变写指针 buffer.writeByte(5) => PooledUnsafeDirectByteBuf(ridx: 0, widx: 5, cap: 9/100)

getBytes、getByte() 与 setBytes()、setByte() 系列,唯一的区别就是 get/set 不会改变读写指针,而 read/write 会改变读写指针。


//只有read方法改变指针  
byte[] bytes = new byte[buffer.readableBytes()];  
buffer.readBytes(bytes);
print("buffer.readBytes(bytes) => {}\n", buffer);  
// buffer.readBytes(bytes) => PooledUnsafeDirectByteBuf(ridx: 10, widx: 10, cap: 16/100)

release() 与 retain()

由于 Netty 使用了堆外内存,而堆外内存是不被 jvm 直接管理的,也就是说申请到的内存无法被垃圾回收器直接回收,所以需要我们手动回收。

Netty 的 ByteBuf 是通过引用计数的方式管理的,如果一个 ByteBuf 没有地方被引用到,就需要回收底层内存。

默认情况下,当创建完一个 ByteBuf,它的引用为1,然后每次调用 retain() 方法, 它的引用就加一, release() 方法原理是将引用计数减一,减完之后如果发现引用计数为0,则直接回收 ByteBuf 底层的内存。

Test

最后是简单测试程序整合前面的API案例。


public class ByteBufTest {
    public static void main(String[] args) {
        ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(9, 100);
        print("allocate ByteBuf(9, 100)", buffer);
        // write 方法改变写指针,写完之后写指针未到 capacity 的时候,buffer 仍然可写
        buffer.writeBytes(new byte[]{1, 2, 3, 4});
        print("writeBytes(1,2,3,4)", buffer);
        // write 方法改变写指针,写完之后写指针未到 capacity 的时候,buffer 仍然可写, 写完 int 类型之后,写指针增加4
        buffer.writeInt(12);
        print("writeInt(12)", buffer);
        // write 方法改变写指针, 写完之后写指针等于 capacity 的时候,buffer 不可写
        buffer.writeBytes(new byte[]{5});
        print("writeBytes(5)", buffer);
        // write 方法改变写指针,写的时候发现 buffer 不可写则开始扩容,扩容之后 capacity 随即改变
        buffer.writeBytes(new byte[]{6});
        print("writeBytes(6)", buffer);
        // get 方法不改变读写指针
        System.out.println("getByte(3) return: " + buffer.getByte(3));
        System.out.println("getShort(3) return: " + buffer.getShort(3));
        System.out.println("getInt(3) return: " + buffer.getInt(3));
        print("getByte()", buffer);
        // set 方法不改变读写指针
        buffer.setByte(buffer.readableBytes() + 1, 0);
        print("setByte()", buffer);
        // read 方法改变读指针
        byte[] dst = new byte[buffer.readableBytes()];
        buffer.readBytes(dst);
        print("readBytes(" + dst.length + ")", buffer);
    }
    private static void print(String action, ByteBuf buffer) {
        System.out.println("after ===========" + action + "============");
        System.out.println("capacity(): " + buffer.capacity());
        System.out.println("maxCapacity(): " + buffer.maxCapacity());
        System.out.println("readerIndex(): " + buffer.readerIndex());
        System.out.println("readableBytes(): " + buffer.readableBytes());
        System.out.println("isReadable(): " + buffer.isReadable());
        System.out.println("writerIndex(): " + buffer.writerIndex());
        System.out.println("writableBytes(): " + buffer.writableBytes());
        System.out.println("isWritable(): " + buffer.isWritable());
        System.out.println("maxWritableBytes(): " + buffer.maxWritableBytes());
        System.out.println();
    }
}

最后是个人的实验Test类。


/**  
 * byteBuf 的API测试  
 */  
public class ByteBufTest {  
    public static void main(String[] args) {  
        // 9 代表初始容量, 100代表最大容量  
        ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(9, 100);  
        print("allocate ByteBuf(9,100) => {} \n", buffer);  
        //allocate ByteBuf(9,100) => PooledUnsafeDirectByteBuf(ridx: 0, widx: 0, cap: 9/100)  
        // write 方法改变写指针  
        buffer.writeBytes(new byte[]{1, 2, 3, 4});  
        print("改变写指针 writeBytes(new byte[]{1,2,3,4}) => {} \n", buffer);  
        // 改变写指针 writeBytes(new byte[]{1,2,3,4}) => PooledUnsafeDirectByteBuf(ridx: 0, widx: 4, cap: 9/100)  
        // write 改变写指针,如果没有到达 capacity 依然可以写入,写入 int 之后写指针增加4  
        buffer.writeInt(12);  
        print("buffer.writeInt(12) => {}\n", buffer);  
        // buffer.writeInt(12) => PooledUnsafeDirectByteBuf(ridx: 0, widx: 8, cap: 9/100)  
        // 继续改变写指针,当前写入等于  initialCapacity 这个初始值之后将不能继续写入  
        buffer.writeBytes(new byte[]{5});  
        print("writeBytes(new byte[]{5}) => {}\n", buffer);  
        // writeBytes(new byte[]{5}) => PooledUnsafeDirectByteBuf(ridx: 0, widx: 9, cap: 9/100)  
        // 继续写入指针,此时发现 已经超过 initialCapacity 的值,此时会进行扩容  
        buffer.writeBytes(new byte[]{6});  
        print("writeBytes(new byte[]{6}) => {}\n", buffer);  
        // writeBytes(new byte[]{6}) => PooledUnsafeDirectByteBuf(ridx: 0, widx: 10, cap: 16/100)  
        // get 方法调用之后不改变读指针  
        print("getByte(3) return => {}\n", buffer.getByte(3));  
        print("getShort(3) return => {}\n", buffer.getShort(3));  
        print("getInt(3) return => {}\n", buffer.getInt(3));  
        print("getChar(3) return => {}\n", buffer.getChar(3));  
        /*  
       getByte(3) return => 4        getShort(3) return => 1024        getInt(3) return => 67108864        getChar(3) return => Ѐ  
        * */  
        // set 方法不改变读写指针  
        buffer.setByte(buffer.readableBytes() + 1, 0);  
        print("setByte(buffer.readableBytes() + 1, 0) => {}\n", buffer);  
        // setByte(buffer.readableBytes() + 1, 0) => PooledUnsafeDirectByteBuf(ridx: 0, widx: 10, cap: 16/100)  
        //只有read方法改变指针  
        byte[] bytes = new byte[buffer.readableBytes()];  
        buffer.readBytes(bytes);  
        print("buffer.readBytes(bytes) => {}\n", buffer);  
        // buffer.readBytes(bytes) => PooledUnsafeDirectByteBuf(ridx: 10, widx: 10, cap: 16/100)  
        print("buffer.readBytes(readBuffer); => {}\n", buffer);  
        ByteBuf readBuffer = ByteBufAllocator.DEFAULT.buffer(6, 6);  
        // 原始writeIndex要有足够空间可读  
//        buffer.writeBytes(new byte[]{5,1,1,1,1,1,1,1});  
//        buffer.writeBytes(new byte[]{5});  
        //  readerIndex(10) + length(6) exceeds writerIndex(11): PooledUnsafeDirectByteBuf(ridx: 10, widx: 11, cap: 16/100)        buffer.readBytes(readBuffer);  
        System.err.println(readBuffer.readableBytes());  
//        buffer.readBytes(readBuffer);  
        // readerIndex(10) + length(9) exceeds writerIndex(10): PooledUnsafeDirectByteBuf(ridx: 10, widx: 10, cap: 16/100)  
    }  
}

写在最后

比较简单的一个章节,主要介绍ByteBuf在Java中的使用,整个使用过程简单易懂十分清晰。

相关文章
|
6月前
|
Java API 容器
《跟闪电侠学Netty》阅读笔记 - 数据载体ByteBuf
《跟闪电侠学Netty》阅读笔记 - 数据载体ByteBuf
132 0
|
6月前
|
Java
【Netty 网络通信】传统IO方式处理网络IO数据
【1月更文挑战第9天】【Netty 网络通信】传统IO方式处理网络IO数据
|
6月前
|
缓存 网络协议 算法
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析
《跟闪电侠学Netty》阅读笔记 - Netty入门程序解析
209 0
|
5月前
|
移动开发 前端开发 网络协议
技术笔记:Netty专题(六)
技术笔记:Netty专题(六)
39 0
|
5月前
netty查看ByteBuf工具
netty查看ByteBuf工具
|
6月前
|
JSON 移动开发 网络协议
数据拆散与黏连:深入剖析Netty中的半包与粘包问题
数据拆散与黏连:深入剖析Netty中的半包与粘包问题
157 0
|
6月前
|
消息中间件 缓存 Java
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty
《跟闪电侠学Netty》阅读笔记 - 开篇入门Netty
170 0
|
存储 Java Unix
【Netty技术专题】「原理分析系列」Netty强大特性之ByteBuf零拷贝技术原理分析
【Netty技术专题】「原理分析系列」Netty强大特性之ByteBuf零拷贝技术原理分析
196 0
【Netty技术专题】「原理分析系列」Netty强大特性之ByteBuf零拷贝技术原理分析
|
存储 Java 索引
Netty原理:ByteBuf对Nio bytebuffer做了什么导致效率提升?(1)
Netty原理:ByteBuf对Nio bytebuffer做了什么导致效率提升?(1)
Netty原理:ByteBuf对Nio bytebuffer做了什么导致效率提升?(1)
|
存储 索引
Netty原理:ByteBuf对Nio bytebuffer做了什么导致效率提升?(2)
Netty原理:ByteBuf对Nio bytebuffer做了什么导致效率提升?(2)