1. ByteBuf

2. 问题描述

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

3. 问题定位及修改

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

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

禁用(DISABLED) – 完全禁止泄露检测,省点消耗。
简单(SIMPLE) – 默认等级,告诉我们取样的1%的ByteBuf是否发生了泄露,但总共一次只打印一次,看不到就没有了。
高级(ADVANCED) – 告诉我们取样的1%的ByteBuf发生泄露的地方。每种类型的泄漏(创建的地方与访问路径一致)只打印一次。对性能有影响。
偏执(PARANOID) – 跟高级选项类似,但此选项检测所有ByteBuf,而不仅仅是取样的那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.
Created at:
io.netty.buffer.AdvancedLeakAwareByteBuf.writeBytes(AdvancedLeakAwareByteBuf.java:604)
io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:849)
com.pinnet.protocol.hwmodbus.message.ModbusMessageRunnable.run(ModbusMessageRunnable.java:46)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
java.lang.Thread.run(Thread.java:748)

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

修改:

buffer.readBytes(4).release();

举例2:

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.
#1:
io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:273)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1380)
io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1159)
io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1194)
io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
#2:
io.netty.buffer.AdvancedLeakAwareByteBuf.getUnsignedShort(AdvancedLeakAwareByteBuf.java:172)
io.netty.handler.codec.LengthFieldBasedFrameDecoder.getUnadjustedFrameLength(LengthFieldBasedFrameDecoder.java:469)
io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:417)
com.pinnet.protocol.hwmodbus.tcp.MobusLengthDecoder.decode(MobusLengthDecoder.java:32)
#3:
io.netty.buffer.AdvancedLeakAwareByteBuf.order(AdvancedLeakAwareByteBuf.java:70)
io.netty.handler.codec.LengthFieldBasedFrameDecoder.getUnadjustedFrameLength(LengthFieldBasedFrameDecoder.java:462)
io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:417)
com.pinnet.protocol.hwmodbus.tcp.MobusLengthDecoder.decode(MobusLengthDecoder.java:32)
io.netty.handler.codec.LengthFieldBasedFrameDecoder.decode(LengthFieldBasedFrameDecoder.java:343)
io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)
io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
#4:
Hint: 'decoder' will handle the message from this point.
#5:
Hint: 'idleHandler' will handle the message from this point.

 修改:解码器中释放Bytebuf in

public class MobusLengthDecoder extends LengthFieldBasedFrameDecoder {

    public MobusLengthDecoder(ByteOrder byteOrder, int maxFrameLength,
int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment,
int initialBytesToStrip, boolean failFast) {
super(byteOrder, maxFrameLength, lengthFieldOffset, lengthFieldLength,
lengthAdjustment, initialBytesToStrip, failFast);
} @Override
protected Object decode(ChannelHandlerContext ctx,
io.netty.buffer.ByteBuf in) throws Exception { ByteBuf buf = (ByteBuf) super.decode(ctx, in);
// LEAK: ByteBuf.release() was not called before it's garbage-collected.
in.release(); ...
} }

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. CSS代码命名惯例语义化的方法

    CSS代码的命名惯例一直是大家热门讨论的话题.今天暴风彬彬想通过分析一个流行三栏布局中的必要元素,来为大家讲解关于使用语义化方法替代结构化方法来命名CSS类的建议和指导. 您还可以参考彬Go的相关文章 ...

  2. SVG动画制作工具 , 从此抛弃臃肿的gif

    VG简介 只要是程序员的你,你不得不知道svg图片,它可以无限任意放大拉伸都不会损失画质,就像系统字体一样可以无限矢量放大,svg更高级是可以用来制作矢量动画,现在各大浏览器和系统基本对svg已经支持 ...

  3. Spring-Boot中如何使用多线程处理任务

    看到这个标题,相信不少人会感到疑惑,回忆你们自己的场景会发现,在Spring的项目中很少有使用多线程处理任务的,没错,大多数时候我们都是使用Spring MVC开发的web项目,默认的Controll ...

  4. Python 执行tail文件并操作

    def log_search(self, logfile, search_content, timeout=10): import time import subprocess import sele ...

  5. 利用 Dockerfile 定制镜像

    镜像的定制实际上就是定制每一层所添加的配置.文件. 如果我们可以把每一层修改.安装.构建.操作的命令都写入一个脚本,用这个脚本来构建.定制镜像, 那么之前提及的无法重复的问题.镜像构建透明性的问题.体 ...

  6. centos7 RPM命令安装操作

    RPM 安装操作 命令: rpm -i 需要安装的包文件名 举例如下: rpm -i example.rpm 安装 example.rpm 包: rpm -iv example.rpm 安装 exam ...

  7. Docker 尝试安装rabbitmq实践笔记

    docker pull rabbitmq 自定義的rabbitmq Dockerfile # base image FROM rabbitmq:3.7-management # running req ...

  8. yii2中使用定义在 params.php文件中的配置

    yii2 使用 配置文件中在 params 的配置, 可以用 Yii::$app->params['key1']形式访问 参考 yii can't access Yii::$app->pa ...

  9. COGS2353 【HZOI2015】有标号的DAG计数 I

    题面 题目描述 给定一正整数n,对n个点有标号的有向无环图(可以不连通)进行计数,输出答案mod 10007的结果 输入格式 一个正整数n 输出格式 一个数,表示答案 样例输入 3 样例输出 25 提 ...

  10. Windows 子网掩码

    子网掩码(subnet mask)又叫网络掩码.地址掩码.子网络遮罩,它是一种用来指明一个IP地址的哪些位标识的是主机所在的子网,以及哪些位标识的是主机的位掩码.子网掩码不能单独存在,它必须结合IP地 ...