title: netty的bytebuf总结
date: 2017-02-10 10:59:41
tags:
category: netty
java原生api ByteBuffer的弊端
1.ByteBuffer长度固定,一旦分配完成,它的容量不能动态扩展和收缩,当需要编码的POJO对象大于ByteBuffer的容量时,会发生索引越界异常;
2.ByteBuffer只有一个标识位置的指针position,读写的时候需要手工调用flip()和rewind()等,使用者必须小心谨慎地处理这些API,否则很容易导致程序处理失败;
3.api复杂,功能简单。netty的ByteBuff提供了更多灵活的api。
@Test
public void testByteBuffer() throws Exception {
ByteBuffer byteBuffer = ByteBuffer.allocate(100);
byteBuffer.put("我是一些内容".getBytes());
byteBuffer.flip();
byte[] container = new byte[byteBuffer.remaining()];
byteBuffer.get(container);
System.out.println(new String(container));
}
这是一个经典的
分配一个100字节的bytebuffer,放入字节内容。(注意你是不能超过100字节的,尝试放入更长的内容会溢出,因为底层就是一个平平无奇的字节数组)
然后flip()将limit置于实际内容之后。如果你没做这一步,或者顺序不对,放后面去了,都会报错。
因为后面的api会读到数组里面没有放内容的部分。
然后按bytebuffer返回的remaining内容的大小,创建一个数组。读内容进去。再转码变成想要的。
可以看出这样用其实很细节,底层和琐碎……
netty将底层的postion指针,重设计为读写两个分开的Index。
netty的ByteBuf的实现是底层相当于将Bytebuffer底层的position分开2个,一个readerIndex,一个writerIndex.这样读写的时候避免了不停的flip和rewind。
netty可以自动进行容量检查,扩容,简化了write系列的api使用
将上面的
ByteBuffer byteBuffer = ByteBuffer.allocate(100);
修改为2个字节。运行将抛出java.nio.BufferOverflowException异常
很明显,Bytebuffer不会自动扩容。但是ByteBuff的api会自动检查不超过最大缓存的前提下自动扩容。避免手动检查。
netty的discardReadBytes()
这个方法可以释放已经读过的数据,如果不调用,会造成缓冲扩容,浪费内存。但是调用之后,底层会进行内存复制,将可写的数组空间放在一起。所以会有性能损失。2者间的权衡需要注意。
网友评论