为什么JMX报告的JVM Heap Usage Max会随着时间的推移而发生变化?

时间:2012-08-10 15:55:49

标签: java jvm heap

我的JVM堆max在名称节点上配置为8GB,用于我的一个hadoop集群。当我使用JMX监视JVM时,报告的最大值会不断波动,如附图所示。

http://highlycaffeinated.com/assets/images/heapmax.png

我只在我的hadoop集群中的一个(最活跃的)上看到这种行为。在其他群集上,报告的最大值保持固定在配置的值。有关报告的最大值会发生变化的任何想法吗?

更新

java版本是“1.6.0_20”

使用以下行在hadoop-env.sh中设置堆最大值:

export HADOOP_NAMENODE_OPTS="-Xmx8G -Dcom.sun.management.jmxremote.port=8004 $JMX_SHARED_PROPS"

ps显示:

hadoop 27605 1 99 Jul30 ? 11-07:23:13 /usr/lib/jvm/jre/bin/java -Xmx1000m -Xmx8G

更新2:

昨晚在启动命令行中添加了-Xms8G开关:

export HADOOP_NAMENODE_OPTS="-Xms8G -Xmx8G -Dcom.sun.management.jmxremote.port=8004 $JMX_SHARED_PROPS"

如下图所示,虽然图案似乎已经改变,但最大值仍然有所不同。

http://highlycaffeinated.com/assets/images/heapmax2.png

更新3:

这是一个新的图表,也显示了非堆最大值,它保持不变:

http://highlycaffeinated.com/assets/images/heapmax3.png

2 个答案:

答案 0 :(得分:1)

根据MemoryMXBean文档,内存使用情况分为两类:“Heap”和“Non-Heap”内存。非堆类别的描述说:

  

Java虚拟机管理堆以外的内存(称为非堆内存)。   Java虚拟机具有在所有线程之间共享的方法区域。方法区域属于非堆内存。它存储每类结构,例如运行时常量池,字段和方法数据,以及方法和构造函数的代码。它是在Java虚拟机启动时创建的。

     

方法区域在逻辑上是堆的一部分,但Java虚拟机实现可能选择不垃圾收集或压缩它。与堆类似,方法区域可以是固定大小的,也可以是扩展和收缩的。方法区域的内存不需要是连续的。

这个描述听起来很像永久代(PermGen),它确实是堆的一部分,并且使用-Xmx标志分配内存。我不确定为什么他们决定单独报告这个,因为它是堆的一部分。

我怀疑您看到的波动是JVM缩小并增加永久生成的结果,这将导致报告的非PermGen使用的最大堆空间相应地更改。如果你能得到JMX报告的Heap和Non-Heap maxes的总和,并且这个总和保持在8G的限制,那将验证这个假设。

答案 1 :(得分:0)

一种可能性是JVM幸存者空间在max-size中波动。

JMX通过HeapMemoryUsage.max属性报告的JVM max-size不是堆的实际最大大小(即使用-Xmx设置的那个)

报告的值是最大堆大小减去最大幸存者空间大小

要获取总的最大堆大小,请添加两个jmx属性:

java.lang:type=Memory/HeapMemoryUsage.max + java.lang:type=MemoryPool,name=Survivor Space/Usage.max

(在oracle jdk 1.7.0_45上测试)