netty使用ResourceLeakDetector检测内存泄漏问题

相关参数

-Dio.netty.noResourceLeakDetection=false # 就版本是否禁用泄漏检测, 默认不禁用, 已过时, 新版本建议用检测级别配置设置
-Dio.netty.leakDetectionLevel=PARANOID  #旧版本配置, paranoid级别检测
-Dio.netty.leakDetection.level=advanced  #新版本配置, advanced级别检测
-Dio.netty.leakDetection.targetRecords=4  #发生泄漏目标记录数, 默认4个, 超出会丢弃, 如果有提示丢弃的存在, 可以适当调大
-Dio.netty.leakDetection.samplingInterval=128  #检测采样率设置, 默认128次采样一次

检测级别:

级别描述
DISABLED禁止泄漏检测。只有详尽测试之后才应该设置这个值。
SIMPLE使用1%的默认采样率检测, 默认级别。适合大部分场景。
ADVANCED使用默认采样率, 但是有泄漏出现, 会打印详细信息
PARANOID偏执模式, 全量采样, 如果有泄漏出现, 会打印详细信息。

测试代码:

    @Test
    public void test2() throws Exception {
        PooledByteBufAllocator allocator = new PooledByteBufAllocator(true);
        IntStream.range(0, 128).forEach(i->{
            ByteBuf bf = allocator.directBuffer(100);
//            bf.release();
//            bf = null;
            System.gc();
        });
        TimeUnit.SECONDS.sleep(11);
    }

junit5+embeddedchannel 检测handler内存泄漏问题

添加jvm参数 -Dio.netty.leakDetection.level=paranoid

//测试的TestServerHandler代码
@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf bf = (ByteBuf)msg;
        System.out.println(ci+" channel read msg: "+bf.toString(CharsetUtil.UTF_8));
        //不加这一行将会产生内存泄漏
  //      ReferenceCountUtil.safeRelease(bf);

    }

@Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ci+" channel read completed!");
        ctx.writeAndFlush(Unpooled.copiedBuffer((ci+
                " finished recieved your message!").getBytes(CharsetUtil.UTF_8)));
        //因为netty内存泄漏检测是通过gc触发的, 所以这里要加个主动gc的代码
        System.gc();
        System.out.println("gc finished.");
    }
//单元测试代码
    private void testServerChannelHandler(){
        EmbeddedChannel ec = new EmbeddedChannel();
        ChannelPipeline pipeline = ec.pipeline();
        pipeline.addLast(new TestServerHandler()).addLast(new LoggingHandler(LogLevel.INFO));
        
        //模拟分配的buffer数据
        ByteBuf buffer = ec.config().getAllocator().buffer();
        buffer.writeBytes("test".getBytes(StandardCharsets.UTF_8));
        
        //将测试数据写入channel
        ec.writeInbound(buffer);
        ec.finishAndReleaseAll();
    }

//    @Test
//用的4.1.75版本, 这里总是第三次才能打印出leak信息, 不知道为什么, 后面有时间研究下源码, 看看为什么会这样。
    @RepeatedTest(3)
    public void test() throws Exception {
        testServerChannelHandler();
        TimeUnit.SECONDS.sleep(1);
    }

测试报告中会提示发生泄漏的地方

ERROR io.netty.util.ResourceLeakDetector - LEAK: ByteBuf.release() was not called before it’s garbage-collected. See https://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records:
#1:
io.netty.buffer.AdvancedLeakAwareByteBuf.toString(AdvancedLeakAwareByteBuf.java:743)
com.example.testcases.netty.server.handler.TestServerHandler.channelRead(TestServerHandler.java:22)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值