1. ByteBuf

2. 问题描述

日志记录中报堆外内存溢出。

3. 问题定位及修改

Netty提供了ByteBuf泄露的检测机制。

JVM启动参数中添加: -Dio.netty.leakDetectionLevel=advanced , log4j2.xml配置io.netty日志记录即可。

  1. 禁用(DISABLED 完全禁止泄露检测,省点消耗。
  2. 简单(SIMPLE 默认等级,告诉我们取样的1%的ByteBuf是否发生了泄露,但总共一次只打印一次,看不到就没有了。
  3. 高级(ADVANCED 告诉我们取样的1%的ByteBuf发生泄露的地方。每种类型的泄漏(创建的地方与访问路径一致)只打印一次。对性能有影响。
  4. 偏执(PARANOID 跟高级选项类似,但此选项检测所有ByteBuf,而不仅仅是取样的那1%。对性能有绝大的影响。

检测到如下泄露点,

举例1

  1. 13:29:25.273 [MODBUS_MESSAGE_POOL-thread-14] [] [] [] ERROR io.netty.util.ResourceLeakDetector - LEAK: ByteBuf.release() was not called before it's garbage-collected. See http://netty.io/wiki/reference-counted-objects.html for more information.
  2. Created at:
  3. io.netty.buffer.AdvancedLeakAwareByteBuf.writeBytes(AdvancedLeakAwareByteBuf.java:604)
  4. io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:849)
  5. com.pinnet.protocol.hwmodbus.message.ModbusMessageRunnable.run(ModbusMessageRunnable.java:46)
  6. java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
  7. java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
  8. java.lang.Thread.run(Thread.java:748)

可以看到readBytes()创建后,没有释放。

修改:

  1. buffer.readBytes(4).release();

举例2:

  1. 2018-06-30 13:29:25.278 [MESSAGE_POOL-thread-14] [] [] [] ERROR io.netty.util.ResourceLeakDetector - LEAK: ByteBuf.release() was not called before it's garbage-collected. See http://netty.io/wiki/reference-counted-objects.html for more information.
  2. #1:
  3. io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:273)
  4. io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
  5. io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
  6. io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
  7. io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
  8. io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
  9. io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
  10. io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
  11. io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1380)
  12. io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1159)
  13. io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1194)
  14. io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
  15. #2:
  16. io.netty.buffer.AdvancedLeakAwareByteBuf.getUnsignedShort(AdvancedLeakAwareByteBuf.java:172)
  17. io.netty.handler.codec.LengthFieldBasedFrameDecoder.getUnadjustedFrameLength(LengthFieldBasedFrameDecoder.java:469)
  18. io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:417)
  19. com.pinnet.protocol.hwmodbus.tcp.MobusLengthDecoder.decode(MobusLengthDecoder.java:32)
  20. #3:
  21. io.netty.buffer.AdvancedLeakAwareByteBuf.order(AdvancedLeakAwareByteBuf.java:70)
  22. io.netty.handler.codec.LengthFieldBasedFrameDecoder.getUnadjustedFrameLength(LengthFieldBasedFrameDecoder.java:462)
  23. io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:417)
  24. com.pinnet.protocol.hwmodbus.tcp.MobusLengthDecoder.decode(MobusLengthDecoder.java:32)
  25. io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:343)
  26. io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
  27. io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)
  28. io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
  29. #4:
  30. Hint: 'decoder' will handle the message from this point.
  31. #5:
  32. Hint: 'idleHandler' will handle the message from this point.

 修改:解码器中释放Bytebuf in

  1. public class MobusLengthDecoder extends LengthFieldBasedFrameDecoder {
  2.  
  3. public MobusLengthDecoder(ByteOrder byteOrder, int maxFrameLength,
  4. int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment,
  5. int initialBytesToStrip, boolean failFast) {
  6. super(byteOrder, maxFrameLength, lengthFieldOffset, lengthFieldLength,
  7. lengthAdjustment, initialBytesToStrip, failFast);
  8. }
  9.  
  10. @Override
  11. protected Object decode(ChannelHandlerContext ctx,
  12. io.netty.buffer.ByteBuf in) throws Exception {
  13.  
  14. ByteBuf buf = (ByteBuf) super.decode(ctx, in);
  15. // LEAK: ByteBuf.release() was not called before it's garbage-collected.
  16. in.release();
  17.  
  18. ...
  19. }
  20.  
  21. }

Netty ByteBuf泄露定位修改。的更多相关文章

  1. 对于 Netty ByteBuf 的零拷贝(Zero Copy) 的理解

    此文章已同步发布在我的 segmentfault 专栏. 根据 Wiki 对 Zero-copy 的定义: "Zero-copy" describes computer opera ...

  2. 双11线上压测netty内存泄露

    最近线上压测,机器学习模型第一次应用到线上经历双11大促.JSF微服务有报错 LEAK: ByteBuf.release() was not called before it's garbage-co ...

  3. Netty ByteBuf(图解之 2)| 秒懂

    目录 Netty ByteBuf(图解二):API 图解 源码工程 写在前面 ByteBuf 的四个逻辑部分 ByteBuf 的三个指针 ByteBuf 的三组方法 ByteBuf 的引用计数 Byt ...

  4. IOS免越狱虚拟定位修改工具共享 Jocation

    Jocation IOS虚拟定位修改器 具体使用方法可以按照 location cleaned软件相同的操作. 主要是因为本人有一部 IphoneX 和Iphone Xs Max 网上的locatio ...

  5. netty byteBuf (二)

    netty重新定义了byteBuf 而没使用jdk byteBuffer netty byteBuf与jdk  byteBuffer的区别 (1)jdk buffer长度固定  byteBuf超过最大 ...

  6. 从一次netty 内存泄露问题来看netty对POST请求的解析

    背景 最近生产环境一个基于 netty 的网关服务频繁 full gc 观察内存占用,并把时间维度拉的比较长,可以看到可用内存有明显的下降趋势 出现这种情况,按往常的经验,多半是内存泄露了 问题定位 ...

  7. Netty ByteBuf源码分析

    Netty的ByteBuf是JDK中ByteBuffer的升级版,提供了NIO buffer和byte数组的抽象视图. ByteBuf的主要类集成关系: (图片来自Netty权威指南,图中有一个画错的 ...

  8. netty ByteBuf分析

    1.Heap Buffer(堆缓冲区) 2.Direct Buffer(直接缓冲区) 3.Composite Buffer(复合缓冲区) 4.PooledByteBuf 池缓冲 readerInex ...

  9. Netty ByteBuf梳理

    我们知道,网络数据的基本单位总是字节.Java NIO提供了ByteBuffer作为它的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐. Netty的ByteBuffer替代品是ByteBuf, ...

随机推荐

  1. ES6 学习 -- 解构赋值

    一.数组解构 **数组解构,解构出来的值跟数组下标是一一对应的,如果左边变量多于右边数组,则左边后面部分变量值为undefined,如果右边数组元素个数多于左边解构变量个数,则左边变量全都有值,且一一 ...

  2. Docker的概念及基本用法

    Docker是PaaS供应商dotCloud开源的一个基于LXC 的高级容器引擎,源代码托管在 GitHub 上, 基于Go语言开发并遵从Apache 2.0协议开源.Docker提供了一种在安全.可 ...

  3. MySQL基本命令脚本

    一.基本命令 1.启动服务 说明:以管理员身份运行cmd 格式:net start 服务名称 示例:net start mysql57 2.停止服务 说明:以管理员身份运行cmd 格式:net sto ...

  4. scala中Tuple简单使用

    /** * Tuple简单使用记录 * 最大22个参数 */ object TupleUse { def main(args: Array[String]): Unit = { // 简单Tuple ...

  5. VPGAME的Kubernetes迁移实践

    VPGAME 是集赛事运营.媒体资讯.大数据分析.玩家社群.游戏周边等为一体的综合电竞服务平台.总部位于中国杭州,在上海和美国西雅图分别设立了电竞大数据研发中心和 AI 研发中心.本文将讲述 VPGA ...

  6. selenium python bindings 元素定位

    1. 辅助 Firepath Firefox是所有做前端的必不可少的浏览器因为firebug的页面元素显示很清晰.用selenium 去定位元素的时候Firefox还有一个非常友好的工具就是firep ...

  7. android studio 正式版本

    注意:以下 Android Studio 下载链接全是 dl.google.com 开头的官方下载,无需tizi,建议用浏览器直接从官方原始链接下载,不要用迅雷下载.不要用迅雷下载.不要用迅雷下载,重 ...

  8. jquery判断是pc端还是移动端

    原文地址:https://www.cnblogs.com/mo-cha/p/6038872.html $(function(){ var system = { win: false, mac: fal ...

  9. HUD1686-Oulipo-kmp模板题/哈希模板题

    The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e ...

  10. 通过JBOSS服务器来实现JMS消息传送

    首先必须启动JBOSS服务器,以便于充当JMS传递消息的中间键: JBOSS消息发送端: package test; import java.util.concurrent.CountDownLatc ...