如何使用java内存直方图“jmap”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24033875/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 09:49:26  来源:igfitidea点击:

How to use java memory histogram "jmap"

javaout-of-memoryjmap

提问by Alex

We have java streaming server running in production and it requires ~10GB of RAM for operation so we have 32GB installed. Memory is gradually increased until limit is reached and out-of-memory exceptions pop up.

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

I have trouble pinpointing what objects are accumulating over time because histogram and memory dump numbers do not match the system reported memory usage, namely java process occupies a little more than max 20GB (so out-of-memory exceptions are justified) but histogram and memory dump shows total of 6.4GB used.

由于直方图和内存转储数字与系统报告的内存使用情况不匹配,我无法确定哪些对象随着时间的推移而累积,即 java 进程占用的内存超过最大 20GB(因此内存不足异常是合理的)但直方图和内存dump 显示总共使用了 6.4GB。

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

How to get information about memory in unknown occupied segment that is not shown in histogram ?

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

I used jmap -J-d64 -histo <pid> > <file>command to generate histogram.

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

Process has following memory segments mapped, shown sorted by size

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

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

Total size of all java objects reported by jmap fits in 0x61F580000: 6666.5MBsegment.

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

My guess is that larger segment the 0x2DE000000: 13333.5MBholds the leaked objects because histogram shows normal memory usage for this application.

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

Is there a way to find out what is occupying other memory not included in histogram ?

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

How can I detect If the closed-source part of server is using native extensions to allocate system memory instead of java memory ? In that case we would not see out-of-memory exceptions right ?

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

Here is htop output:

这是 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 -

Here is partial histogram output:

这是部分直方图输出:

 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

The java version is:

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)

回答by Aditya

The memory is divided between the

内存分为

  1. Heap space - Whats on the heap, reachable from the root
  2. Perm gen - the loaded classes etc. static variables also come here
  3. Stack space - temporary method level variables stored on the stack, thread locals
  1. 堆空间 - 堆上的内容,可从根访问
  2. Perm gen - 加载的类等静态变量也来到这里
  3. 堆栈空间 - 存储在堆栈上的临时方法级变量,线程局部变量

Depending on how the JMap is extracted, the perm gen might not be included. The stack space is never included. These might contribute to the extra memory that you are not seeing in your heap dump.

根据提取 JMap 的方式,可能不包括 perm gen。从不包括堆栈空间。这些可能会导致您在堆转储中看不到的额外内存。

Check these probable causes -

检查这些可能的原因 -

  1. Are you using dynamically generated classes, causing perm gen to be really big?
  2. Are you using Thread Locals and storing a lot of data on them ?
  3. local method variables that might be continuously growing in size due to some reason?
  1. 您是否使用动态生成的类,导致 perm gen 非常大?
  2. 您是否正在使用 Thread Locals 并在其上存储大量数据?
  3. 由于某种原因,局部方法变量的大小可能不断增长?

Locally

本地

If it reproduces locally, you can use JConsole to check all the memory space sizes to figure out when so much non heap space is being used.

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

Try loading the jmap into Memory Analyzerto check the leak suspects. It might show you any information you might be missing.

尝试将jmap加载到内存分析器中以检查泄漏嫌疑人。它可能会显示您可能遗漏的任何信息。

For further reading, also see theseguides

如需进一步阅读,另请参阅这些指南

Try the following settings on the production setup

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

  1. Increase the heap size by setting the Xmx
  2. Increase the permgenspace using -XX:MaxPermSize=256m
  3. set the following flags -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -Xloggc:/path/to/garbage.log
  4. Enable GC on perm gen
  1. 通过设置Xmx 来增加堆大小
  2. 使用-XX:MaxPermSize=256m增加永久空间
  3. 设置以下标志 -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -Xloggc:/path/to/garbage.log
  4. 在 perm gen 上启用 GC

To diagnose the problem better, please provide

为了更好地诊断问题,请提供

  1. The stack trace of the OutOfMemory error should give information about what is causing the issue.
  2. The JVM flags you are supplying at the start of the process.
  1. OutOfMemory 错误的堆栈跟踪应提供有关导致问题的原因的信息。
  2. 您在流程开始时提供的 JVM 标志。