netty之ResourceLeakDetector的使用与实现

通过WeakReference和ReferenceQueue做针对需要手动释放的资源的侦测

使用

  1. 设置日志级别:
ServerBootstrap b =new ServerBootstrap();
b.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 2048)
.handler(new LoggingHandler(LogLevel.DEBUG))
.childHandler(new ChildChannelHandler()); 2017-01-19 10:04:49 [ nioEventLoopGroup-1-0:1628830 ] - [ ERROR ] LEAK: ByteBuf.release() was not called before it's garbage-coll...
  1. ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED);或者通过JVM参数配置

    日志:
2017-01-19 10:35:59  [ nioEventLoopGroup-1-0:665092 ] - [ ERROR ]  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: 5
#5:
io.netty.buffer.AdvancedLeakAwareByteBuf.readBytes(AdvancedLeakAwareByteBuf.java:435)

分析

[ ERROR ] LEAK:

// ResourceLeakDetector
protected void reportTracedLeak(String resourceType, String records) {
logger.error(
"LEAK: {}.release() was not called before it's garbage-collected. " +
"See http://netty.io/wiki/reference-counted-objects.html for more information.{}",
resourceType, records);
} private void reportLeak() {
if (!logger.isErrorEnabled()) {
clearRefQueue();
return;
} // Detect and report previous leaks.
for (;;) {
@SuppressWarnings("unchecked")
DefaultResourceLeak ref = (DefaultResourceLeak) refQueue.poll(); // 为什么能拿到?什么时候 放进去的?是weakreference回收过程中放进去的,相当于GC过程让你插入hook。那为什么被GC了还有资源泄露呢?这个问题其实是这样的,泄露是池化内存等那些需要手动释放资源。
if (ref == null) {
break;
} if (!ref.dispose()) { // return allLeaks.remove(this); 所以当有人显式释放过,那么此处就返回false 就不会往下走report了
continue;
} String records = ref.toString();
if (reportedLeaks.putIfAbsent(records, Boolean.TRUE) == null) {
if (records.isEmpty()) {
reportUntracedLeak(resourceType);
} else {
reportTracedLeak(resourceType, records);
}
}
}
}

基本实现原理是:

  1. 通过DefaultResourceLeak继承自WeakReference,借助WeakReference的GC特性完成。WeakReference的GC特性是当这个对象没有被其他强引用对象引用时,仅仅被WeakReference引用(或者其他weak引用)时,会在下一次GC时回收,回收过程中会将被回收的引用放到ReferenceQueue中。此处的ReferenceQueue又是在创建DefaultResourceLeak时通过构造参数传入的。
  2. 不时poll那个ReferenceQueue队列,当拿到对象时看起dispose是否被调用过,如果没有则证明没有显示释放,则report出来。
  3. 每次创建池化buf对象时,便会创建DefaultResourceLeak,并在touch等API中调用其record方法,追踪其申请使用的地方。在开启了泄露追踪后,buf会被包装,比如包装成AdvancedLeakAwareByteBuf。
  4. 侦测reportLeak不是每次都调用,当小雨PARANOID级别是在申请buf时按随机数比例调。PARANOID级别是全调。

此处资源泄露,是指那种需要手动释放的资源,因为引用他的对象已经不在程序逻辑中使用了,那么最终会被GC回收,但是那种需要手动释放的资源不显式释放就泄露了。比如内存池,比方说里面有5个杯子,你用的buf指向一个杯子被你占着,你不用时没显式告诉内存池说这个杯子不用了,那么就一直占着,但是buf对象不用了会被GC回收,那么此时内存池资源就泄露了。

[netty4][netty-common]netty之ResourceLeakDetector的使用与实现的更多相关文章

  1. 【Netty】Netty入门之WebSocket小例子

    服务端: 引入Netty依赖 <!-- netty --> <dependency> <groupId>io.netty</groupId> <a ...

  2. Netty学习——Netty和Protobuf的整合(二)

    Netty学习——Netty和Protobuf的整合(二) 这程序是有瑕疵的,解码器那里不通用,耦合性太强,有两个很明显的问题,但是要怎么解决呢?如:再加一个内部类型 Person2,之前的代码就不能 ...

  3. Netty学习——Netty和Protobuf的整合(一)

    Netty学习——Netty和Protobuf的整合 Protobuf作为序列化的工具,将序列化后的数据,通过Netty来进行在网络上的传输 1.将proto文件里的java包的位置修改一下,然后再执 ...

  4. 【netty】Netty系列之Netty百万级推送服务设计要点

    1. 背景 1.1. 话题来源 最近很多从事移动互联网和物联网开发的同学给我发邮件或者微博私信我,咨询推送服务相关的问题.问题五花八门,在帮助大家答疑解惑的过程中,我也对问题进行了总结,大概可以归纳为 ...

  5. 【Netty】Netty核心组件介绍

    一.前言 前篇博文体验了Netty的第一个示例,下面接着学习Netty的组件和其设计. 二.核心组件 2.1. Channel.EventLoop和ChannelFuture Netty中的核心组件包 ...

  6. 【Netty】Netty传输

    一.前言 在简单学习了Netty中的组件后,接着学习Netty中数据的传输细节. 二.传输 2.1 传输示例 Netty中的数据传输都是使用的字节类型,下面通过一个实例进行说明,该实例中服务器接受请求 ...

  7. 【Netty】Netty之ByteBuf

    一.前言 前面已经学习了Netty中传输部分,现在接着学习Netty中的ByteBuf. 二.ByteBuf 2.1 ByteBuf API 在网络上传输的数据形式为Byte,Java NIO提供了B ...

  8. 【Netty】Netty之Bootstrapping

    一.前言 前面已经学习了Netty的EventLoop以及线程模型,接着学习Netty的Bootstrapping. 二.Bootstrapping 在学习了Netty中的很多组件后,如何将这些组件有 ...

  9. netty学习--netty源码中的部分util方法

    io.netty.buffer.AbstractByteBuf#calculateNewCapacity  申请内存空间 private int calculateNewCapacity(int mi ...

  10. Netty 之 Netty生产级的心跳和重连机制

    https://blog.csdn.net/z69183787/article/details/52625095 最近工作比较忙,但闲暇之余还是看了阿里的冯家春(fengjiachun)的github ...

随机推荐

  1. Cordova iPhone 刘海屏 和 安卓瀑布屏 等异形屏幕的适配处理

    1.  在cordova项目的config.xml中指定StatusBarOverlaysWebView(需要cordova-plugin-statusbar插件支持),表示应用界面是否覆盖状态栏(系 ...

  2. c++ string类型举例(递归预习的边界)

    #include <iostream> #include <string> using namespace std; int main ( ) { string str; // ...

  3. SpringBoot环境下使用测试类注入Mapper接口报错解决

    当我们在进行开发中难免会要用到测试类,而且测试类要注入Mapper接口,如果测试运行的时候包空指针异常,看看测试类上面的注解是否用对! 正常测试我们需要用到的注解有这些: @SpringBootTes ...

  4. Airflow Dag可视化管理编辑工具Airflow Console

    Airflow Console: https://github.com/Ryan-Miao/airflow-console Apache Airflow扩展组件, 可以辅助生成dag, 并存储到git ...

  5. Python List max()方法

    描述 max() 方法返回列表元素中的最大值.高佣联盟 www.cgewang.com 语法 max()方法语法: max(list) 参数 list -- 要返回最大值的列表. 返回值 返回列表元素 ...

  6. PHP timezone_offset_get() 函数

    ------------恢复内容开始------------ 实例 返回相对于 GMT 的时区偏移: <?php$tz=timezone_open("Asia/Taipei" ...

  7. JDBC(1)-数据库连接和CRUD操作

    关于jdbc的全部jar包 链接:https://pan.baidu.com/s/1peofgu89SpepTTYuZuphNw 提取码:vd5v 一.获取数据库连接 1. Driver接口介绍 ja ...

  8. luogu P4008 [NOI2003]文本编辑器 splay 块状链表

    LINK:文本编辑器 这个东西感觉块状链表写细节挺多 (块状链表本来就难写 解释一下块状链表的做法:其实是一个个数组块 然后利用链表给链接起来 每个块的大小为sqrt(n). 这样插入删除的时候直接暴 ...

  9. 关于ORACLE索引的几种扫描方式

    ------------恢复内容开始------------ ------------恢复内容开始------------ 一条sql执行的效率因执行计划的差异而影响,经常说这条sql走索引了,那条s ...

  10. yum自建离线仓库

    1.步骤 centOS的安装包,完整版最好--everyhing版本 解压缩 将文件夹内Packages文件导入系统 执行命令如下: 1. mv ./Packages/ /mnt/ 2. create ...