4

我们正在运行grpc-java0.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 内存。(注意,它grpcnetty用作它的通信层。)这似乎是不正常的。即便如此,堆内对象也无法占用 4GB 内存。这必须是由于堆外内存使用情况,例如netty.

是否存在堆外内存泄漏?

为什么会发生这种情况?以及如何解决或诊断这个问题?

4

1 回答 1

1

升级到 grpc-java 0.9.0 或更高版本(引入 Netty 4.1 Beta6 或更高版本)解决了这个问题。目前尚不清楚问题是错误还是由于在与分配缓冲区不同的线程上释放缓冲区而导致效率低下。

于 2016-01-19T23:50:36.617 回答