如何使用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
How to use java memory histogram "jmap"
提问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.5MB
segment.
jmap 报告的所有 java 对象的总大小适合0x61F580000: 6666.5MB
段。
My guess is that larger segment the 0x2DE000000: 13333.5MB
holds 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
内存分为
- Heap space - Whats on the heap, reachable from the root
- Perm gen - the loaded classes etc. static variables also come here
- Stack space - temporary method level variables stored on the stack, thread locals
- 堆空间 - 堆上的内容,可从根访问
- Perm gen - 加载的类等静态变量也来到这里
- 堆栈空间 - 存储在堆栈上的临时方法级变量,线程局部变量
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 -
检查这些可能的原因 -
- Are you using dynamically generated classes, causing perm gen to be really big?
- Are you using Thread Locals and storing a lot of data on them ?
- local method variables that might be continuously growing in size due to some reason?
- 您是否使用动态生成的类,导致 perm gen 非常大?
- 您是否正在使用 Thread Locals 并在其上存储大量数据?
- 由于某种原因,局部方法变量的大小可能不断增长?
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
在生产设置中尝试以下设置
- Increase the heap size by setting the Xmx
- Increase the permgenspace using -XX:MaxPermSize=256m
- set the following flags -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -Xloggc:/path/to/garbage.log
- Enable GC on perm gen
- 通过设置Xmx 来增加堆大小
- 使用-XX:MaxPermSize=256m增加永久空间
- 设置以下标志 -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -Xloggc:/path/to/garbage.log
- 在 perm gen 上启用 GC
To diagnose the problem better, please provide
为了更好地诊断问题,请提供
- The stack trace of the OutOfMemory error should give information about what is causing the issue.
- The JVM flags you are supplying at the start of the process.
- OutOfMemory 错误的堆栈跟踪应提供有关导致问题的原因的信息。
- 您在流程开始时提供的 JVM 标志。