我们正在运行grpc-java
0.8.0 版服务器来处理远程调用。服务器逻辑非常简单,它只是从数据库中获取由给定 id 指定的数据并将它们设置到redis
缓存中。
JVM 参数配置为-Xss256k -Xmx8G
. top
一旦服务器启动并处理大约 400 QPS ,JVM 就会占用 4GB(RES in )内存。我发出 jmap 命令jmap -histo:live <pid>
并得到以下转储文件:
num #instances #bytes class name
----------------------------------------------
1: 4998400 119961600 io.netty.buffer.PoolThreadCache$MemoryRegionCache$Entry
2: 212415 23503536 [B
3: 11076 20170816 [Lio.netty.buffer.PoolThreadCache$MemoryRegionCache$Entry;
4: 70853 10010904 [C
5: 28819 2518640 [Lio.netty.util.Recycler$DefaultHandle;
6: 31232 1998848 com.mysql.jdbc.ConnectionPropertiesImpl$BooleanConnectionProperty
7: 7287 1764136 [I
8: 70000 1680000 java.lang.String
9: 45766 1464512 java.util.Hashtable$Entry
10: 134 1291992 [D
11: 14376 1265088 io.netty.buffer.PooledUnsafeDirectByteBuf
12: 5527 1160200 [Ljava.util.HashMap$Node;
13: 16340 1116584 [[B
从中我们可以看到有大量io.netty.buffer.PoolThreadCache$MemoryRegionCache$Entry
实例占用了大约 100MB 内存。(注意,它grpc
被netty
用作它的通信层。)这似乎是不正常的。即便如此,堆内对象也无法占用 4GB 内存。这必须是由于堆外内存使用情况,例如netty
.
是否存在堆外内存泄漏?
为什么会发生这种情况?以及如何解决或诊断这个问题?