java - Netty 中的 ByteBuffers 导致内存泄漏

标签 java netty

我创建了一个小型 Netty 服务器来计算 BigInteger 的阶乘并发送结果。代码如下。

阶乘.java

public class Factorial {

    private int port;

    public Factorial(int port) {
        this.port = port;
    }

    public void run(int threadcount) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup(threadcount);
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .childHandler(new ChannelInitializer<SocketChannel>() {
                 @Override
                 public void initChannel(SocketChannel ch) throws Exception {
                     ch.pipeline().addLast(new FactorialHandler());
                 }
             })
             .option(ChannelOption.SO_BACKLOG, 128)          
             .childOption(ChannelOption.SO_KEEPALIVE, true); 

            ChannelFuture f = b.bind(port).sync(); 

            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        int port = 15000;
        new Factorial(port).run(Integer.parseInt(args[0]));
    }
}

FactorialHandler.java

public class FactorialHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) { 
        BigInteger result = BigInteger.ONE;
        String resultString;
        for (int i=2000; i>0; i--)
            result = result.multiply(BigInteger.valueOf(i));
        resultString = result.toString().substring(0, 3)+"\n";
        ByteBuf buf = Unpooled.copiedBuffer(resultString.getBytes());
        ctx.write(buf);
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

当我运行它时,出现了以下错误

Jun 08, 2018 5:28:09 PM io.netty.util.ResourceLeakDetector reportTracedLeak
SEVERE: LEAK: ByteBuf.release() was not called before it's garbage-collected. See http://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records:

如给定链接中所述,我通过在 ctx.flush() 之后调用 channelRead 方法中的 buf.release() 释放了 ByteBuffer。

但是当我这样做时,服务器开始抛出以下异常

io.netty.util.IllegalReferenceCountException: refCnt: 0, increment: 1

谁能告诉我如何解决这个问题?

最佳答案

问题不在于出站 ByteBuf。出站 ByteBufs 总是为您处理(参见 OutboundMessages )。问题是入站 ByteBuf。我在看着你,FactorialHandler。它扩展了 ChannelInboundHandlerAdapter .请注意 JavaDoc 中的这一点:

Be aware that messages are not released after the channelRead(ChannelHandlerContext, Object) method returns automatically. If you are looking for a ChannelInboundHandler implementation that releases the received messages automatically, please see SimpleChannelInboundHandler.

您的处理程序具有如下签名:

public void channelRead(ChannelHandlerContext ctx, Object msg)

那个 msg,(顺便说一下,你不使用它)实际上是一个 ByteBuf,这正是上面的 JavaDoc 注释警告你的。 (在没有任何其他 ChannelHandler 的情况下,消息将始终是 ByteBuf 的实例。)

所以你的选择是:

  1. 使用 SimpleChannelInboundHandler 为您清理该引用。
  2. 在处理程序结束时,使用 ReferenceCountUtil.release(java.lang.Object msg) 释放入站 ByteBuf .

关于java - Netty 中的 ByteBuffers 导致内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50760506/

相关文章:

java - 查看邻居节点,前面有n个节点

java - 将 PDFBox 迁移到 2.x 时出现 GetPages 错误

java - 从服务器向客户端发送消息

Netty 4. ByteToMessageCodec之后的并行处理

java - 使用 Netty 的 Java 服务器端和 C++ 或 Objective C 的客户端

java - Websocket 阻止来自服务器的传入请求

java - 关闭 Netty 服务器本身

java - 如何使用 For 循环从数据库中拆分不同 LinearLayout 中的名称

java - 有没有办法在调用构造函数时检查我的对象的实例?

java - 如何在我的 Web 应用程序中实现附属链接?