跳到主要内容

十、Netty 教程 – ByteBuf详解

作者:唐亚峰 | 出自:唐亚峰博客

> 原生的ByteBuffer存在哪些问题呢,Netty为什么会设计ByteBuf呢,它的工作原理是什么…..

ByteBuffer存在的问题

ByteBufferJDK1.4中提供的java.nio.Buffer, 在内存中预留指定大小的存储空间来存放临时数据,其他Buffer的子类有:CharBufferDoubleBufferFloatBufferIntBufferLongBufferShortBuffer

  • ByteBuffer的长度是固定的,一旦分配完成,容量就无法动态扩容收缩,分多了会浪费内存,分少了存放大的数据时会索引越界(当传输数据大于初始化长度时,会出现BufferOverflowException索引越界的异常),所以使用ByteBuffer时,为了解决这个问题,我们一般每次put操作时,都会对可用空间进行校检,如果剩余空间不足,需要重新创建一个新的ByteBuffer,然后将旧的ByteBuffer复制到新的ByteBuffer中去

  • ByteBuffer中只有通过position获得当前可操作的位置,调用get()方法,返回ByteBuffer[postion]处的值,如果是调用put方法,将数据放入ByteBuffer[postion]的位置

  • API功能有限,部分高级功能并不支持,需开发者自己实现,且使用原生ByteBuffer较为困难(不适合小白专业户)

ByteBuf与ByteBuffer的区别

> 不同ByteBuf实现原理各不相同,我们先看最基本的ByteBuf与原生的ByteBuffer的区别

ByteBuf buf = Unpooled.buffer(10);
buf.writeBytes("鏖战八方QQ群391619659".getBytes());//扩容算法稍后讲解
System.out.println("Netty:" + buf);
byte[] by = new byte[buf.readableBytes()];
buf.readBytes(by);
System.out.println("Netty:" + new String(by));
System.out.println("//////////////////////////////////////////无耻的分割线//////////////////////////////////////////");
ByteBuffer bf1 = ByteBuffer.allocate(100);
bf1.put("鏖战八方QQ群391619659".getBytes());
System.out.println("JDK:"+bf1);
System.out.println("当前指针:" + bf1.position());
byte[] by1 = new byte[bf1.remaining()];
System.out.println(by1.length);//What's 居然是74
bf1.get(by1);
System.out.println("未使用flip:"+new String(by1));//居然是空的
System.out.println("//////////////////////////////////////////无耻的分割线//////////////////////////////////////////");
ByteBuffer bf2 = ByteBuffer.allocate(100);
bf2.put("鏖战八方QQ群391619659".getBytes());
System.out.println("JDK:"+bf2);
System.out.println("当前指针:" + bf2.position());
bf2.flip();
byte[] by2 = new byte[bf2.remaining()];
System.out.println(by2.length);//是26了
bf2.get(by2);
System.out.println("使用flip:"+new String(by2));//拿到了