Netty源码分析之ByteBuf引用计数
引用计数是一种常用的内存管理机制,是指将资源的被引用次数保存起来,当被引用次数变为零时就将其释放的过程。Netty在4.x版本开始使用引用计数机制进行部分对象的管理,其实现思路并不是特别复杂,它主要涉及跟踪某个对象被引用的次数。在Netty具体代码中需要通过引用计数进行内存管理的对象,会基于ReferenceCounted接口实现,其中引用计数大于0时则代表该对象被引用不会释放,当引用计数减少到0时,该对象就会被释放。通过引用计数机制,Netty可以很好的实现内存管理,引用计数减少到0时要么直接释放内存,要么放回内存池中重复利用。
1、基本示例
下面先通过一个简单示例看下Netty中引用计数机制的使用
@Override public void channelRead(ChannelHandlerContext ctx, Object msg) { ByteBuf recvBuffer = (ByteBuf) msg;// 申请ByteBuf 需要主动释放 if(recvBuffer.isDirect()){ System.err.println(true); } PooledByteBufAllocator allocator = new PooledByteBufAllocator(true); ByteBuf sendBuffer = allocator.buffer();//申请池化直接内存 System.err.println("sendBuffer的引用计数:"+sendBuffer.refCnt()); sendBuffer.retain(); System.err.println("sendBuffer的引用计数:"+sendBuffer.refCnt()); sendBuffer.release(); System.err.println("sendBuffer的引用计数:"+sendBuffer.refCnt());
try { byte[] bytesReady = new byte[recvBuffer.readableBytes()]; recvBuffer.readBytes(bytesReady); System.out.println("channelRead收到数据:"+ BytesUtils.toHexString(bytesReady)); byte[] sendBytes = new byte[] {0x7E,0x01,0x02,0x7e}; sendBuffer.writeBytes(sendBytes); ctx.writeAndFlush(sendBuffer); System.err.println("sendBuffer的引用计数:"+sendBuffer.refCnt()); }catch (Exception e) { // TODO: handle exception System.err.println(e.getMessage()); }finally { System.err.println("recvBuffer的引用计数:"+recvBuffer.refCnt()); recvBuffer.release(); //此处需要释放 System.err.println("recvBuffer的引用计数:"+recvBuffer.refCnt()); } }