ネッティーのResourceLeakDetectorの使用と実装
弱い参照とReferenceQueueのために行う手動で解放する必要が検出リソースを
使用
- ログレベルを設定します。
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...
- 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);
}
}
}
}
基本的な原理は、達成することです。
- DefaultResourceLeakが弱い参照から継承されたことで、GCの性質によって完成弱い参照。オブジェクトのGC弱い参照特性次回、リカバリプロセスがReferenceQueueに参照して回収されるときに他の文献、(弱いまたは他の参照)単に弱い参照基準は、GCが回収されるときに参照されるオブジェクトは強くありません。あなたが渡されたパラメータを構築することによりDefaultResourceLeakを作成するときに、ここでReferenceQueueです。
- 時々の世論調査にオブジェクトがルックスを得ることですReferenceQueueキューは、その後、リリースの証拠を示さないではない場合、呼び出されているかどうか処分すること、レポートが出てきました。
- BUFオブジェクトのプールが作成されるたびに、それはDefaultResourceLeakを作成し、そのようなAPI、トラックアプリケーション用途などのタッチ方法でその記録を呼び出します。オープン、bufにリークをトレースした後にそのようなAdvancedLeakAwareByteBufに包装として、包装されるであろう。
- 検出reportLeakは常に呼び出されていない時に乱数大きな割合BUFアプリケーションの時点で雨PARANOIDレベル。PARANOIDレベルは、フルトーンです。
ここでは、リソースリーク、彼はプログラムロジックで使用されていないオブジェクト参照されているので、それが最終的にGCを回復されますが、手動でのリリースに必要なリソースの種類を明示的にリークした上でリリースされていない、手動でのリリースに必要なリソースの種類を指し、 。このようなメモリプールとして、カップはあなたによって占有にあなたがポイントbufは使用し、5杯があると言うあなたが明示的にこのカップノーを言うためにメモリプールを教えていないとき、それは占領されているが、bufがオブジェクトではありませんGCを回復するので、この時間は、それはメモリプールのリソースをリークします。