我在java进程中遇到了一个奇怪的问题,它在Linux VM上消耗了大量资源。 该过程的顶部输出如下:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1182 blabla 20 0 25.5g 21g 45m S 382.9 33.9 139840:17 java
所以这表明该过程实际上消耗了21G的物理内存?
当更详细地检查过程时,我可以看到它是用-Xmx4G启动的。对于" top"上显示的21G是否有任何合理的解释? ? (忽略下面ps输出的第一个-Xmx)
blabla@dtraflocorh391:~ $ ps aux | grep 1182
blabla 1182 249 33.8 26716716 22363868 ? Sl Feb13 139847:01 java -Xms32M -Xmx128M -showversion -Djavax.xml.stream.XMLEventFactory=com.ctc.wstx.stax.WstxEventFactory -Djavax.xml.stream.XMLInputFactory=com.ctc.wstx.stax.WstxInputFactory -Djavax.xml.stream.XMLOutputFactory=com.ctc.wstx.stax.WstxOutputFactory -Xms256M -Xmx4G -verbose:gc -XX:+PrintGCTimeStamps ... ... ...
... ...
答案 0 :(得分:2)
所以这表明该过程实际上消耗了21G的物理内存?
是。 "顶部"命令报告操作系统提供的进程物理内存使用情况。没有理由不信任它。
对于" top"上显示的21G是否有任何合理的解释? ?
可能是大量的堆外内存分配,或者是大型内存映射文件,或者......大量的线程堆栈。
或其他可能的东西。
请注意,VIRT
数字表示已经以某种方式提交给进程的总虚拟内存。 ' RES'图表示用于保存' VIRT'的子集的总物理内存使用量。当前"在"。
因此,VIRT图可以更好地衡量Java进程所要求的内存资源。事实上,VIRT和RES是如此不同,这一事实证明了你的过程导致了#th; thrashing"。
另见:
答案 1 :(得分:2)
-Xmx
控制最大堆大小 - 实际上是存储使用new
关键字创建的内容。
Java有其他内存池 - 用于执行堆栈,用于缓存JIT编译代码,用于存储加载的类和动态创建的类,用于内存映射文件,本机代码使用的堆空间(JNI,或者只是Hotspot本身) ):见How is the java memory pool divided?
JConsole是一个可用于查看Java程序使用内存的工具。一旦JConsole告诉你哪个区域大/满,你就可以开始说明为什么会这样了。
例如,我曾经有一个程序为每个解析加载一个新的Jackson对象映射器 - 而这个版本的Jackson有一个错误,它在非堆内存中留下了动态类,从来没有GCd。您的问题可能是这个,或者可能是完全不同的问题。 JConsole将告诉你。