docker运行java进程消耗的额外内存不明原因

dde*_*ele 14 java memory docker

我们有什么 :

  • 在docker容器中运行的Java应用程序
  • 没有调用本机代码,没有处理启动,没有引用DLL/.so文件.
  • JVM args: -Xmx256m -XX:NativeMemoryTracking=summary
  • Docker硬内存限制设置为 768m
  • JVM似乎正常(正常的GC循环,没有内存泄漏,没有OOM)
  • Docker内存不断增长,直到达到硬限制(768m),导致杀死并重新启动容器.

问题 :

  • 为什么Docker统计数据内存不断增长(导致每天都会遇到硬内存限制),尽管JVM似乎表现在其极限范围内.

在此输入图像描述

  • 使用其他微服务,我们看不到这种行为

在此输入图像描述

JVM

在JVM方面,我们没有注意到任何特殊的东西:

在此输入图像描述

Docker统计输出:

492.8MiB / 768MiB     64.17%              

[ec2-user@ip-10-180-28-222 ~]$ docker exec 34d7 jcmd 1 VM.native_memory summary
1:

Native Memory Tracking:

Total: reserved=1731355KB, committed=472227KB
-                 Java Heap (reserved=262144KB, committed=262144KB)
                            (mmap: reserved=262144KB, committed=262144KB)

-                     Class (reserved=1131805KB, committed=92829KB)
                            (classes #16224)
                            (malloc=7453KB #20996)
                            (mmap: reserved=1124352KB, committed=85376KB)

-                    Thread (reserved=29932KB, committed=29932KB)
                            (thread #30)
                            (stack: reserved=29772KB, committed=29772KB)
                            (malloc=94KB #151)
                            (arena=66KB #55)

-                      Code (reserved=255659KB, committed=35507KB)
                            (malloc=6059KB #9814)
                            (mmap: reserved=249600KB, committed=29448KB)

-                        GC (reserved=15369KB, committed=15369KB)
                            (malloc=5785KB #547)
                            (mmap: reserved=9584KB, committed=9584KB)

-                  Compiler (reserved=190KB, committed=190KB)
                            (malloc=59KB #858)
                            (arena=131KB #6)

-                  Internal (reserved=7849KB, committed=7849KB)
                            (malloc=7817KB #18468)
                            (mmap: reserved=32KB, committed=32KB)

-                    Symbol (reserved=20018KB, committed=20018KB)
                            (malloc=17325KB #175818)
                            (arena=2693KB #1)

-    Native Memory Tracking (reserved=3558KB, committed=3558KB)
                            (malloc=10KB #120)
                            (tracking overhead=3548KB)

-               Arena Chunk (reserved=4830KB, committed=4830KB)
                            (malloc=4830KB)
Run Code Online (Sandbox Code Playgroud)

跑了大约20个小时

649.6MiB / 768MiB     84.59%               

[ec2-user@ip-10-180-28-222 ~]$ docker exec 34d7 jcmd 1 VM.native_memory summary
1:

Native Memory Tracking:

Total: reserved=1741020KB, committed=510928KB
-                 Java Heap (reserved=262144KB, committed=262144KB)
                            (mmap: reserved=262144KB, committed=262144KB)

-                     Class (reserved=1138319KB, committed=100495KB)
                            (classes #16390)
                            (malloc=7823KB #30851)
                            (mmap: reserved=1130496KB, committed=92672KB)

-                    Thread (reserved=30996KB, committed=30996KB)
                            (thread #31)
                            (stack: reserved=30800KB, committed=30800KB)
                            (malloc=97KB #156)
                            (arena=99KB #57)

-                      Code (reserved=261330KB, committed=69062KB)
                            (malloc=11730KB #16047)
                            (mmap: reserved=249600KB, committed=57332KB)

-                        GC (reserved=15363KB, committed=15363KB)
                            (malloc=5779KB #334)
                            (mmap: reserved=9584KB, committed=9584KB)

-                  Compiler (reserved=223KB, committed=223KB)
                            (malloc=92KB #1246)
                            (arena=131KB #6)

-                  Internal (reserved=8358KB, committed=8358KB)
                            (malloc=8326KB #18561)
                            (mmap: reserved=32KB, committed=32KB)

-                    Symbol (reserved=20253KB, committed=20253KB)
                            (malloc=17527KB #177997)
                            (arena=2725KB #1)

-    Native Memory Tracking (reserved=3846KB, committed=3846KB)
                            (malloc=10KB #127)
                            (tracking overhead=3836KB)

-               Arena Chunk (reserved=188KB, committed=188KB)
                            (malloc=188KB)
Run Code Online (Sandbox Code Playgroud)

意见

观察20小时后到目前为止我们所知道的:

  • Docker统计数据从跳跃492.8MiB649.6MiB
  • JVM提交的本机内存从跳转472227KB510928KB
  • docker stats和JVM提交的本机内存之间的差距似乎在增长.(它在哪里649.6MiB - 510928KB以及为什么它在增长)
  • 在此期间,JVM统计数据保持正常.

所以我不知道我还能在JVM端调试什么.我理解java需要的不仅仅是堆(因此是本机内存跟踪),但jvm本机内存跟踪器报告的内容和docker统计数据之间仍然存在大约150米的差距.我怎样才能获得更多关于内存去向的见解?

jan*_*isz 4

JVM 报告的内存并不代表一切。

\n\n
\n

JVM\xe2\x80\x99s 内存占用

\n\n

那么,什么因素影响了 JVM 内存占用呢?我们大多数运行过 Java 应用程序的人都知道如何设置最大堆空间。但是\n \xe2\x80\x99s 实际上对内存占用的影响更大:

\n\n
    \n
  • 原生 JRE
  • \n
  • 烫发/元空间
  • \n
  • JIT字节码
  • \n
  • JNI
  • \n
  • 蔚来
  • \n
  • 线程数
  • \n
\n\n

当我们想要设置 Docker 容器的内存限制时,需要记住很多事情。并且还将容器内存限制设置为最大堆空间,可能还不够\xe2\x80\xa6

\n\n

JVM 和 CPU

\n\n

让\xe2\x80\x99s 简单看一下 JVM 如何调整其运行的节点上可用的处理器/核心的数量。实际上有许多参数,默认情况下是根据核心数进行初始化的。

\n\n
    \n
  • JIT 编译器线程的 \xe2\x99\xaf
  • \n
  • \xe2\x99\xaf 垃圾收集线程
  • \n
  • 公共 fork-join 池中线程的 \xe2\x99\xaf\n \xe2\x80\xa6
  • \n
\n\n

因此,如果 JVM 在 32 核节点上运行(并且没有覆盖默认节点),JVM 将生成 32 个垃圾收集线程、32 个 JIT 编译器线程、\xe2\x80\xa6。来源

\n
\n\n

为了防止出现此问题,您应该使用+UseContainerSupport(自 Java 10 中默认启用的 8u191 起可用)和 可能-XX:MaxRAMPercentage=90.0或更少,具体取决于您观察到的总使用内存。有关更多信息,请参阅这个那个

\n\n

我强烈推荐:“没有人将 Java 放入容器中:Ken Sipe”,来自 JavaZone

\n