如何使用java内存直方图" jmap"

时间:2014-06-04 09:33:57

标签: java out-of-memory jmap

我们有java流媒体服务器在生产中运行,它需要~10GB的RAM才能运行,所以我们安装了32GB。内存逐渐增加,直到达到限制并弹出内存不足异常。

我无法确定哪些对象随时间累积,因为直方图和内存转储数与系统报告的内存使用量不匹配,即java进程占用的空间超过20GB(因此内存异常是合理的)但是直方图和内存转储显示总共使用了6.4GB。

process : 19.8G
Java
reported:  6.4G
---------------
unknown 
occupied
segment : 13.4G

如何获取直方图中未显示的未知占用段中的内存信息?

我用jmap -J-d64 -histo <pid> > <file>命令生成直方图。

进程有以下内存段映射,按大小排序

0x2DE000000: 13333.5MB
0x61F580000: 6666.5MB
0x7C0340000: 1020.8MB
0x7FBFF33C9000: 716.2MB
0x7FC086A75000: 196.9MB
0x7FB85C000000: 64.0MB
0x7FBAC0000000: 64.0MB
...

jmap报告的所有java对象的总大小适合0x61F580000: 6666.5MB段。

我的猜测是0x2DE000000: 13333.5MB更大的段保存泄漏的对象,因为直方图显示了此应用程序的正常内存使用情况。

有没有办法找出占用直方图中未包含的其他内存的内容?

如何检测服务器的闭源部分是否使用本机扩展来分配系统内存而不是java内存?在那种情况下,我们不会看到内存不足的异常吗?

这是htop输出:

  Mem[|||||||||||||||||||||31670/31988MB]     Tasks: 87; 35 running
  Swp[||||||||||||||||||   16361/32579MB]     Load average: 39.33 36.00 34.72
                                              Uptime: 44 days, 15:08:19

  PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command
 3498 root       20   0 51.5G 19.8G  4516 S 151. 63.4     176h java -server -Xmx20000M -

这是部分直方图输出:

 num     #instances         #bytes  class name
----------------------------------------------
   1:       1134597     5834904800  [B
   2:        407694      144032664  [Ljava.lang.Object;
   3:       2018132      111547480  [C
   4:        100217       71842520  [I
   5:        581934       55865664  com.wowza.wms.httpstreamer.cupertinostreaming.livestreampacketizer.CupertinoRepeaterHolder
   6:        568535       36386240  com.wowza.wms.httpstreamer.cupertinostreaming.livestreampacketizer.CupertinoTSHolder
   7:        975220       23405280  java.lang.String
   8:        967713       23225112  com.wowza.wms.amf.AMFObjChunk
   9:        621660       14919840  com.wowza.wms.httpstreamer.cupertinostreaming.livestreampacketizer.LiveStreamingCupertinoBlock
  10:        369892       11836544  java.util.ArrayList$Itr
  11:        184502       11808128  com.wowza.wms.amf.AMFPacket
  12:        329055        7897320  java.util.ArrayList
  13:         55882        6705840  com.wowza.wms.server.RtmpRequestMessage
  14:        200263        6408416  java.util.HashMap$Node
  15:         86784        6248448  com.wowza.wms.httpstreamer.cupertinostreaming.livestreampacketizer.CupertinoPacketHolder
  16:         24815        5360040  com.wowza.wms.media.h264.H264CodecConfigInfo
  17:        209398        5025552  java.lang.StringBuilder
  18:        168061        4033464  com.wowza.util.PacketFragment
  19:        119160        3813120  java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
  20:         93849        3753960  java.util.TreeMap$Entry
  21:        155756        3738144  java.lang.Long
  22:         55881        3576384  com.wowza.wms.server.RtmpResponseMessage
  23:         55760        3568640  com.wowza.util.FasterByteArrayOutputStream
  24:        130452        3130848  java.util.concurrent.LinkedBlockingQueue$Node
  25:         63172        3032256  java.util.HashMap
  26:         58747        2819856  java.nio.HeapByteBuffer
  27:         34830        2800568  [J
  28:         49076        2355648  java.util.TreeMap$AscendingSubMap
  29:         70567        2258144  com.wowza.wms.stream.livepacketizer.LiveStreamPacketizerBase$PacketizerEventHolder
  30:         55721        2228840  org.apache.mina.util.Queue
  31:         54990        2199600  java.util.HashMap$KeyIterator
  32:         58583        1874656  org.apache.mina.common.SimpleByteBufferAllocator$SimpleByteBuffer
  33:        112743        1803888  java.lang.Integer
  34:         55509        1776288  com.wowza.wms.server.ServerHandlerEvent
...
2089:             1             16  sun.util.resources.LocaleData$LocaleDataResourceBundleControl
Total      11078054     6454934408

java版本是:

# java -version
java version "1.8.0_05"
Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)

1 个答案:

答案 0 :(得分:1)

内存分为

  1. 堆空间 - 堆上的什么,可以从根
  2. 到达
  3. Perm gen - 加载的类等静态变量也来到这里
  4. 堆栈空间 - 存储在堆栈上的临时方法级变量,线程本地
  5. 根据JMap的提取方式,可能不包含perm gen。永远不会包含堆栈空间。这些可能会导致您在堆转储中看不到的额外内存。

    检查这些可能的原因 -

    1. 你使用动态生成的类,导致perm gen真的很大吗?
    2. 您是否正在使用Thread Locals并在其上存储大量数据?
    3. 由于某种原因可能会持续增长的本地方法变量?
    4. <强>本地

      如果它在本地再现,您可以使用JConsole检查所有内存空间大小,以确定何时使用非堆空间。

      尝试加载jmap into Memory Analyzer以检查泄漏嫌疑人。它可能会向您显示您可能缺少的任何信息。

      如需进一步阅读,请参阅these guides

      在生产设置中尝试以下设置

      1. 通过设置 Xmx
      2. 来增加堆大小
      3. 使用 -XX增加permgenspace:MaxPermSize = 256m
      4. 设置以下标志 的 -XX:+ PrintTenuringDistribution -XX:+ PrintGCDetails -XX:+ PrintGCTimeStamps -XX:+ HeapDumpOnOutOfMemoryError -Xloggc:/path/to/garbage.log
      5. 在perm gen上启用GC
      6. 要更好地诊断问题,请提供

        1. OutOfMemory错误的堆栈跟踪应提供有关导致问题的原因的信息。
        2. 您在流程开始时提供的JVM标记。