【问题标题】:JVM - XMX limit vs Memory consumed by the processJVM - XMX 限制与进程消耗的内存
【发布时间】:2021-03-29 19:22:06
【问题描述】:

我有 2 个关于 Java 应用程序使用的常驻内存的问题。

一些背景细节:

  • 我有一个使用 -Xms2560M -Xmx2560M 设置的 java 应用程序。
  • Java 应用程序正在容器中运行。 k8s 允许容器最多消耗 4GB。

问题:

有时进程被k8s重启,报错137,显然进程已经达到4GB了。

应用行为:

  • 堆:应用程序的工作方式似乎是使用所有内存,然后释放,然后使用等等。

这张快照说明了这一点。 Y 列是可用的堆内存。 (由((double)Runtime.getRuntime().freeMemory()/Runtime.getRuntime().totalMemory())*100应用程序提取 )

我还可以使用HotSpotDiagnosticMXBean 确认它,它允许创建一个包含可访问对象和一个还包含不可访问对象的转储。

无法访问的那个是 XMX 大小。

此外,这也是我在机器本身上创建转储时看到的,常驻内存可以显示 3GB,而转储的大小为 0.5GB。 (用jcmd拍摄)

第一个问题:

这是合理的行为还是表示内存使用问题? 这似乎不是典型的泄漏。

第二个问题

我看到了更多的问题,试图了解应用程序使用的常驻内存是由什么组成的。
值得一提:

Java using much more memory than heap size (or size correctly Docker memory limit)

Native memory consumed by JVM vs java process total memory usage

不确定这是否可以占 XMX 和 4GB k8s 限制之间的 1-1.5 GB。

如果您要提供某种检查清单来解决问题,那会是什么? (感觉好像只见树木不见森林)

任何可以提供帮助的免费工具? (除了那些用于分析内存转储的)

【问题讨论】:

  • 在某些情况下,一个进程可能会消耗20GB内存,而堆只有2GB。这是否正常,完全取决于应用程序 - 我们不能在不知道您的特定应用程序的情况下说。例如。对于 Cassandra、Elasticsearch 或其他处理大量映射文件的 Java 进程来说,RSS 远远大于堆大小是很典型的。
  • 你提到的帖子已经有了详细的答案。他们还列出了一系列用于分析本机内存问题的工具:Native Memory Tracking、pmap、jemalloc、async-profiler。查看相关的video,它描述了流行的本机内存问题并演示了如何解决这些问题。

标签: java memory memory-leaks garbage-collection jvm


【解决方案1】:

你为堆分配了 2.5 GB,JVM 本身和操作系统组件也会占用一些内存(这里的重击规则是 1 GB,但实际数字可能会有很大差异,尤其是在容器中运行时),所以我们已经是 3.5 GB。

从 Java 8 开始,JVM 将不再将类的代码存储在堆上,而是存储在称为“元空间”的区域中;根据您的程序在做什么、有多少类以及它使用多少个 ClassLoader,这个区域可能很容易增长到 0.5 GB 以上。除了链接帖子中提到的内容之外,还需要考虑这一点。

【讨论】:

    【解决方案2】:

    除了 tquadrat 发布的答案之外,您还必须考虑当应用程序使用由位于堆空间之外但被进程占用的字节缓冲区映射的本机内存时会发生什么。

    【讨论】:

    猜你喜欢
    • 2017-06-19
    • 1970-01-01
    • 2016-09-26
    • 2020-04-01
    • 2020-10-19
    • 2022-06-14
    • 2018-07-25
    • 2012-02-27
    • 1970-01-01
    相关资源
    最近更新 更多