其他分享
首页 > 其他分享> > 【Netty】ByteBuf.release() was not called before it's garbage-collected

【Netty】ByteBuf.release() was not called before it's garbage-collected

作者:互联网

1 现象

2021-02-18 16:17:58.399	2021-02-18 16:17:58.399 ERROR 1 --- [oServerWorker-2] c.c.c.g.p.i.ClientToProxyConnection : (AWAITING_INITIAL) [id: 0xedf191be, L:/172.30.173.45:8080 - R:/172.30.146.1:35754]: Caught an exception on ClientToProxyConnection
2021-02-18 16:17:58.399	io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 16777216 byte(s) of direct memory (used: 2781194413, max: 2793406464)
2021-02-18 16:17:58.399	at io.netty.util.internal.PlatformDependent.incrementMemoryCounter(PlatformDependent.java:725) ~[netty-all-4.1.42.Final.jar:4.1.42.Final]

2021-02-18 16:33:59.636	2021-02-18 16:33:59.636 ERROR 1 --- [oServerWorker-0] i.n.u.ResourceLeakDetector : LEAK: ByteBuf.release() was not called before it's garbage-collected. See https://netty.io/wiki/reference-counted-objects.html for more information.
2021-02-18 16:33:59.636	Recent access records:
2021-02-18 16:33:59.636	#1:
2021-02-18 16:33:59.636	io.netty.handler.codec.http.HttpObjectAggregator$AggregatedFullHttpMessage.release(HttpObjectAggregator.java:379)

2021-02-18 17:13:36.840 ERROR 55896 --- [oServerWorker-3] i.n.u.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:
Created at:
     io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:349)
     io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:187)
     io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:178)
     io.netty.buffer.CompositeByteBuf.allocBuffer(CompositeByteBuf.java:1835)
     io.netty.buffer.CompositeByteBuf.copy(CompositeByteBuf.java:1487)
     io.netty.buffer.AbstractByteBuf.copy(AbstractByteBuf.java:1209)
     io.netty.buffer.WrappedCompositeByteBuf.copy(WrappedCompositeByteBuf.java:493)
	 io.netty.buffer.AdvancedLeakAwareCompositeByteBuf.copy(AdvancedLeakAwareCompositeByteBuf.java:681)
io.netty.handler.codec.http.HttpObjectAggregator$AggregatedFullHttpRequest.copy(HttpObjectAggregator.java:405)
	org.littleshoot.proxy.impl.ClientToProxyConnection.copy(ClientToProxyConnection.java:848)
org.littleshoot.proxy.impl.ClientToProxyConnection.doReadHTTPInitial(ClientToProxyConnection.java:163)
	org.littleshoot.proxy.impl.ClientToProxyConnection.readHTTPInitial(ClientToProxyConnection.java:140)
	org.littleshoot.proxy.impl.ClientToProxyConnection.readHTTPInitial(ClientToProxyConnection.java:56)
	org.littleshoot.proxy.impl.ProxyConnection.readHTTP(ProxyConnection.java:116)
	org.littleshoot.proxy.impl.ProxyConnection.read(ProxyConnection.java:101)
	org.littleshoot.proxy.impl.ProxyConnection.channelRead0(ProxyConnection.java:477)
io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)

2 分析

3 改造

(1)添加直接内存检测日志

int maxMemoryInKb = (int) (PlatformDependent.maxDirectMemory() / 1024);
int used = (int) (PlatformDependent.usedDirectMemory() / 1024);
log.info("netty_direct_memory:used({}k) max({}k)", memoryInKb, used, maxMemoryInKb);

(2)ClientToProxyConnection的copy方法修复

private HttpRequest copy(HttpRequest original) {
    if (original instanceof FullHttpRequest) {
        return original; // 注释掉 ((FullHttpRequest) original).copy();
    } else {
        HttpRequest request = new DefaultHttpRequest(original.protocolVersion(), original.method(), original.uri());
        request.headers().set(original.headers());
        return request;
    }
}

4 本地测试

(1)本地打包应用启动

java -jar -verbose:gc -Xloggc:/tmp/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=3M -XX:-TraceClassUnloading -Djava.io.tmpdir=/tmp -XX:OnOutOfMemoryError=$JAVA_HOME/bin/killjava.sh  -XX:+ExitOnOutOfMemoryError -XX:+UseG1GC -Xss228K -Xmx317161K -Xms317161K -XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M -Dio.netty.leakDetectionLevel=paranoid -Dio.netty.maxDirectMemory=67108864 gateway-app.jar > log.out

注:对溢出检测感兴趣可以看看ResourceLeakDetector、SimpleLeakAwareByteBuf、AbstractByteBufAllocator等几个类。

(2)压测

5 测试环境

(1)提交代码自动化部署至测试环境

(2)压测

6 生产上线

标签:Netty,java,garbage,netty,XX,内存,io,collected,日志
来源: https://www.cnblogs.com/linzhanfly/p/14458404.html