简体   繁体   English

JVM - XMX 限制与进程消耗的 Memory

[英]JVM - XMX limit vs Memory consumed by the process

I have 2 questions regarding the resident memory used by a Java application.关于 Java 应用程序使用的常驻 memory,我有 2 个问题。

Some background details:一些背景细节:

  • I have a java application set up with -Xms2560M -Xmx2560M.我有一个使用 -Xms2560M -Xmx2560M 设置的 java 应用程序。
  • The java application is running in a container. java 应用程序正在容器中运行。 k8s allows the container to consume up to 4GB. k8s 允许容器最多消耗 4GB。

The issue:问题:

Sometimes the process is restarted by k8s, error 137, apparently the process has reached 4GB.有时进程被k8s重启,错误137,显然进程已经达到4GB。

Application behaviour:应用行为:

  • Heap: the application seems to work in a way where all memory is used, then freed, then used and so on.堆:应用程序似乎以使用所有 memory 的方式工作,然后释放,然后使用等等。

This snapshot illustrates it.此快照说明了这一点。 The Y column is the free heap memory. Y 列是空闲堆 memory。 (extracted by the application by ((double)Runtime.getRuntime().freeMemory()/Runtime.getRuntime().totalMemory())*100 ) (由应用程序通过((double)Runtime.getRuntime().freeMemory()/Runtime.getRuntime().totalMemory())*100提取)

在此处输入图像描述

I was also able to confirm it using HotSpotDiagnosticMXBean which allows creating a dump with reachable objects and one that also include unreachable objects.我还能够使用HotSpotDiagnosticMXBean来确认它,它允许创建一个包含可访问对象和一个还包含不可访问对象的转储。

The one with the unreachable was at the size of the XMX.无法到达的那个是 XMX 的大小。

In addition, this is also what i see when creating a dump on the machine itself, the resident memory can show 3GB while the size of the dump is 0.5GB.此外,这也是我在机器本身创建转储时看到的,常驻 memory 可以显示 3GB,而转储的大小为 0.5GB。 (taken with jcmd) (使用 jcmd 获取)

First question:第一个问题:

Is this be behaviour reasonable or indicates a memory usage issue?这是行为合理还是表明 memory 使用问题? It doesn't seem like a typical leak.这似乎不是典型的泄漏。

Second question第二个问题

I have seen more questions, trying to understand what the resident memory, used by the application, is comprised of.我看到了更多问题,试图了解应用程序使用的常驻 memory 是由什么组成的。
Worth mentioning:值得一提:

Java using much more memory than heap size (or size correctly Docker memory limit) Java 使用比堆大小更多的 memory(或大小正确 Docker ZCD69B4957F080CD8191ZBFDED3)

And

Native memory consumed by JVM vs java process total memory usage 本机 memory 消耗的 JVM vs java 进程总计 ZCD69B4957F06CD818D7BF3DD618

Not sure if any of this can account for 1-1.5 GB between the XMX and the 4GB k8s limit.不确定这是否可以占 XMX 和 4GB k8s 限制之间的 1-1.5 GB。

If you were to provide some sort of a check list to close in on the problem what will it be?如果您要提供某种检查清单来解决问题,那会是什么? (feels like i can't see the forest for the trees) (感觉就像我不能只见树木不见森林)

Any free tools that can help?任何可以提供帮助的免费工具? (beside the ones for analysing a memory dump) (除了用于分析 memory 转储的那些)

You allocate 2.5 GB for the heap, the JVM itself and the OS components will take also some memory (the rule of thump is here 1 GB, but the real figures may differ significantly, especially when running in a container), so we are already at 3.5 GB.您为堆分配 2.5 GB,JVM 本身和操作系统组件也将占用一些 memory(这里的重击规则是 1 GB,但实际数字可能会有很大差异,尤其是在容器中运行时),所以我们已经3.5 GB。

Since Java 8, the JVM will store the code for the classes not longer on the heap, but in an area called 'metaspace';由于 Java 8,JVM 将不再将类的代码存储在堆上,而是存储在称为“元空间”的区域中; depending on what your program is doing, how many classes and how many ClassLoaders it uses, this area may grow easily above 0.5 GB.根据您的程序在做什么、有多少类以及它使用多少个 ClassLoader,这个区域可能很容易增长到 0.5 GB 以上。 This needs to be considered, in addition to those stuff mentioned in the linked posts.除了链接帖子中提到的那些内容之外,还需要考虑这一点。

As well as the answer posted by tquadrat you also have to consider what would happen when the application uses native memory mapped by byte buffers which is outside of the heap space but taken up by the process.除了 tquadrat 发布的答案之外,您还必须考虑当应用程序使用由位于堆空间之外但被进程占用的字节缓冲区映射的本机 memory 时会发生什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM