netty之堆内存、直接内存、bytebuf(yet)
1 Netty缓冲区——ByteBuf Netty的ByteBuf是一个抽象类,是Netty管辖的内存,里面主要是一些byte数组的读写方法,与其说是抽象类,不如说它是一个接口,因为它里面几乎全是抽象方法,下面是截取它的一部分方法: ByteBuf有四个重要的实现类:PooledDirectByteBuf,PooledHeapByteBuf, UnpooledDirectByteBuf,UnpooledHeapByteBuf, 它们分别代表池化直接内存,池化堆内存,未池化直接内存,未池化堆内存。直接内存代表没有数据从内核空间到用户空间的复制,代表高效;池化代表高效的内存分配和释放。 1.1 内存分配 四种内存分配: // 未池化堆内存 ByteBuf heapByteBuf = Unpooled.buffer(10); // 未池化直接内存 ByteBuf directByteBuf = Unpooled.directBuffer(10); // 池化堆内存 PooledByteBufAllocator allocator = new PooledByteBufAllocator(false); ByteBuf pHeapByteBuf = allocator.buffer(); // 池化直接内存 PooledByteBufAllocator allocator2 = new PooledByteBufAllocator(true); ByteBuf pDirectByteBuf = allocator.buffer(); 复合内存是把上述几种内存复合成一个对象来操作的一种内存。 CompositeByteBuf compositeByteBuf = Unpooled.compositeBuffer(); compositeByteBuf.addComponents(heapByteBuf, directByteBuf, pHeapByteBuf, pDirectByteBuf); 1 2 1.2 内存读写操作 ByteBuf 有两个游标,readerIndex指向已读字节位,writerIndex指向已写字节位。通常我们不会对同一个ByteBuf一边读一边写,因此可以理解为读操作时只存在readerIndex一个游标,写操作时只存在writerIndex一个游标。这两个游标会随着我们的读写操作自动变换位置,也可以手动强行把它们移动到指定位置。 读示例: // 读取前判断可读状态 if (heapByteBuf.isReadable()) { // 计算可读长度 int len = heapByteBuf.readableBytes(); // 可以直接读出到ByteBuf中 ByteBuf read = heapByteBuf.readBytes(len/2); // 也可读出到指定byte数组 byte[] dis = new byte[len/2]; heapByteBuf.readBytes(dis); } 写示例: // 写前判断可写余量 if (heapByteBuf.isWritable()){ // XXX可以是byte[] 和 ByteBuf heapByteBuf.writeBytes(XXX); } 1.3 内存释放 ByteBuf内存释放: ByteBuf抽象类实现了ReferenceCounted接口,实现引用计数功能。引用计数为0时可以释放: directByteBuf.release(); 1 netty在有些地方会自动释放ByteBuf,在有些地方又不会,总结3.1.4的内容:只有未继承SimpleChannelInboundHandler的响应ByteBuf需要手动在业务代码中使用ReferenceCountUtil.release(byteBuf)释放,其他情况,不论是否池化,不论请求还是响应,都由Netty自动释放。 ———————————————— 版权声明:本文为CSDN博主「旧城灯火」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_32717909/article/details/91635714