作者:Nikita Salnikov-Tarnovski 译者:Amanda 校对:
“你好,你能过来看看帮我解决一个奇怪的问题么。”就是这个技术支持案例使我想起写下这篇帖子。眼前的这个问题就是关于不同工具对于可用内存大小检测的差异。
其实就是一个工程师在调查一个应用程序的过高的内存使用情况时发现,尽管该程序已经被指定分配2G堆内存,但是JVM检测工具似乎并不能确定进程实际能用多少内存。例如 jconsole显示可用堆内存为1,963M,然而 jvisualvm 却显示能用2,048M。所以到底哪个工具才是对的,为什么检测结果会出现差异呢?
这确实是个挺奇怪的问题,特别是当最常出现的几种解释理由都被排除后,看来JVM并没有耍一些明显的小花招:
-Xmx和-Xms是相等的,因此检测结果并不会因为堆内存增加而在运行时有所变化。
通过关闭自适应调整策略(-XX:-UseAdaptiveSizePolicy),JVM已经事先被禁止动态调整内存池的大小。
重现差异检测结果
要弄清楚这个问题的第一步就是要明白这些工具的实现原理。通过标准APIs,我们可以用以下简单语句得到可使用的内存信息。
System.out.println("Runtime.getRuntime().maxMemory()="+Runtime.getRuntime().maxMemory());
而且确实,现有检测工具底层也是用这个语句来进行检测。要解决这个问题,首先我们需要一个可重复使用的测试用例。因此,我写了下面这段代码:
package eu.plumbr.test;
//imports skipped for brevity
pu