【问题标题】:Why does the JVM Heap Usage Max as reported by JMX change over time?为什么 JMX 报告的 JVM Heap Usage Max 会随时间变化?
【发布时间】:2012-08-07 23:10:30
【问题描述】:

我的 JVM 堆最大值在我的一个 hadoop 集群的名称节点上配置为 8GB。当我使用 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

【问题讨论】:

  • 我怀疑这个节点上没有设置 max。如果未设置,JVM 将确定使用多少。什么是java版本?
  • 我用 java 版本和最大设置更新了问题。 ps 显示 Xmx 的两个值 - 在所有集群上都是这种方式。第二个值似乎是正在使用的值。
  • 您是否尝试设置 Xms 以查看它是否改变了什么?
  • 没有尝试过 Xms,但我会试一试。它是一个生产集群,所以我不能经常重启。
  • -Xmx1000m -Xmx8G? -Xmx1000m来自哪里?和其他命令行一样吗?

标签: java jvm heap-memory


【解决方案1】:

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

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

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

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

我怀疑您看到的波动是 JVM 缩小和增长永久代的结果,这将导致报告的可用于非永久代使用的最大堆空间相应地发生变化。如果您可以得到 JMX 报告的堆和非堆最大值的总和,并且该总和在 8G 限制下保持不变,那么就可以验证这个假设。

【讨论】:

  • 我添加了另一个图表来显示非堆最大值。正如你所看到的,它保持不变,所以我不认为它是 PermGen。此外,我没有看到任何其他集群的堆最大值变化,只有这个。
  • 哦,好吧,这是一个很好的猜测。我能想到的其他场景:(a)如果 JVM 可以检测到并非所有配置的数量都可从操作系统获得,则报告的最大值可能小于您的配置值,或者(b)堆最大值计算为总和各个 GC 代的最大值,其单个最大值可能不占全部 8GB。但这都是猜测。
  • 实际上是从头开始(a),因为您从 -Xms 开始,它应该在启动时从操作系统请求完整的 8GB。
【解决方案2】:

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

JMX 通过 HeapMemoryUsage.max 属性报告的 JVM 最大大小不是堆的实际最大大小(即带有 -Xmx 的集合)

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

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

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

(在 oracle jdk 1.7.0_45 上测试)

【讨论】:

    猜你喜欢
    • 2023-03-22
    • 2013-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-24
    • 2014-06-26
    • 1970-01-01
    • 2014-11-20
    相关资源
    最近更新 更多