【问题标题】:JVM Native memory tracking how to limit class metadata sizeJVM本机内存跟踪如何限制类元数据大小
【发布时间】:2019-10-31 21:39:17
【问题描述】:

最初的问题是 java 应用程序是 docker 由于内存使用而被 OOM 杀死。 所以我开始使用 NMT 来了解为什么消耗量超过预期。 JVM 版本为 1.8.0_212,支持容器。 docker 使用下一个 java 选项启动

JAVA_OPTS='-XX:+AlwaysPreTouch -Xmx128m -Xms128m -XX:MaxMetaspaceSize=150m -XX:ReservedCodeCacheSize=100m -XX:+UseStringDeduplication -XX:+PrintFlagsFinal -XshowSettings:vm -XX:NativeMemoryTracking=detail' ... -m="450m" --cpu-shares="256" docker-image

本机内存跟踪:

Total: reserved=1464054KB +843KB, committed=344578KB +1359KB

...

-                     Class (reserved=1124594KB +19KB, committed=85066KB +275KB)
                            (classes #15631)
                            (malloc=2290KB +19KB #20081 +27)
                            (mmap: reserved=1122304KB, committed=82776KB +256KB)
...

所有数字都符合预期。唯一的问题是 Class 字段,因为它显示了 ~ 1GB 的保留值,它可以以某种方式减少吗?

【问题讨论】:

  • 为什么?你的问题是提供足够的内存,而不是减少任何东西。
  • 你真的用了 15691 个类,它们就在那里。
  • 1gd 保留,对于我的小型微服务来说似乎太多了,它什么都不做:) 似乎由于某些逻辑(可能是因为 aop-spring)它不断生成新类。而且因为限制是1gb,所以会更新GC
  • 通过-XX:+UseSerialGC参数更改默认GC算法(Parallel GC)可以看到最大的变化。

标签: java docker memory-management jvm


【解决方案1】:

这是Compressed Class Space

默认限制正好是 1GB,可以用-XX:CompressedClassSpaceSize=N 减小。

Native Memory Tracking 输出中的“类”区域包括元空间和压缩类空间,这就是为什么您会看到超过 1GB 的预留空间。但是,保留的内存只是虚拟地址空间的数量——它不占用物理内存页。

更多关于JVM virtual memory

【讨论】:

  • 对我来说 CompressedClassSpaceSize := 148897792。等于 ~ 142 MB。它使用 -XX:+PrintFlagsFinal 打印
  • 这很奇怪。当显式设置 -XX:CompressedClassSpaceSize=150m jvm NMT 显示类保留空间 = 200mb
  • @user2105282 142 MB = 150 - 2*4 = MaxMetaspaceSize - 2*InitialBootClassLoaderMetaspaceSize。在this answer 中解释。
猜你喜欢
  • 1970-01-01
  • 2017-12-11
  • 2015-04-13
  • 2013-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-08
相关资源
最近更新 更多