了解释放资源

时间:2017-12-10 17:08:37

标签: java netty

我正在使用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()
   }
});

1 个答案:

答案 0 :(得分:3)

根据http://netty.io/wiki/reference-counted-objects.html

  

自Netty版本4以来,某些对象的生命周期由其引用计数管理,因此Netty可以在不使用它们时立即将它们(或其共享资源)返回给对象池(或对象分配器)了。垃圾收集和参考队列不提供不可达性的有效实时保证,而引用计数提供了替代机制,但代价是略有不便。

然而,这不是完整的解释。 Netty ByteBuf还可以访问直接HEAP内存。这个内存是特殊的,它不会在垃圾收集器运行时运行,而是抛出异常。

Netty尝试访问堆内存的原因基本上是因为当处理与“通道”一起使用的任何东西时,它会提供大的速度增量,例如将文件从文件复制到套接字,或从套接字1复制到套接字2。比使用数组做同样的事情有更好的性能,其中较低级别首先需要将其转换为java数组,然后在发送数据包时再次返回。

由于堆(直接)内存与垃圾收集器一起工作的方式,这可能意味着在某些情况下,当创建的唯一对象是Netty ByteBufs时,堆内存在垃圾收集器的调用之间变满,因为从垃圾收集器的角度来看,内存从来都不是满的。由于垃圾收集器中的这个夸克,Netty基本上必须制作一个释放方法,以便在不再需要时直接释放内存。