我正在使用Netty来处理HTTP请求/响应。并写下以下ByteBuf的管道:
public class MyBusinessLogic
extends ChannelInboundHandlerAdapter{
public void channelRead(ChannelHandlerContext ctx, Object msg){
ByteBuf bb = ctx.alloc().buffer().writeBytes(//some bytes)
ctx.writeAndFlush(bb, ctx.newPromise())
//I did not release bb here
}
}
在日志中,我收到了类似于“ByteBuf was garbage collected before it was released
”的警告......类似于它。
问题是为什么我们需要自己发布ByteBuf
?无论如何它们都是垃圾收集的。如果我不在这里发布bb
,我可以遇到什么样的麻烦?
将缓冲区释放添加为频道未来侦听器是否正确?
ByteBuf bb = //
ctx.writeAndFlush(response, ctx.newPromise())
.addListener(new ChannelFutureListener(){
public void operationComplete(ChannelFuture f){
buf.release()
}
});
答案 0 :(得分:3)
根据http://netty.io/wiki/reference-counted-objects.html:
自Netty版本4以来,某些对象的生命周期由其引用计数管理,因此Netty可以在不使用它们时立即将它们(或其共享资源)返回给对象池(或对象分配器)了。垃圾收集和参考队列不提供不可达性的有效实时保证,而引用计数提供了替代机制,但代价是略有不便。
然而,这不是完整的解释。 Netty ByteBuf还可以访问直接HEAP内存。这个内存是特殊的,它不会在垃圾收集器运行时运行,而是抛出异常。
Netty尝试访问堆内存的原因基本上是因为当处理与“通道”一起使用的任何东西时,它会提供大的速度增量,例如将文件从文件复制到套接字,或从套接字1复制到套接字2。比使用数组做同样的事情有更好的性能,其中较低级别首先需要将其转换为java数组,然后在发送数据包时再次返回。
由于堆(直接)内存与垃圾收集器一起工作的方式,这可能意味着在某些情况下,当创建的唯一对象是Netty ByteBufs时,堆内存在垃圾收集器的调用之间变满,因为从垃圾收集器的角度来看,内存从来都不是满的。由于垃圾收集器中的这个夸克,Netty基本上必须制作一个释放方法,以便在不再需要时直接释放内存。