-Xmx256m -XX:NativeMemoryTracking=summary
768m
768m
)为止,这导致终止并重启容器。在JVM方面,我们没有发现任何特殊之处:
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)
运行约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)
观察20小时后我们所知道的一切:
492.8MiB
跃升至649.6MiB
472227KB
跳到510928KB
649.6MiB - 510928KB
在哪里,为什么会增长)所以我不知道我还能在JVM端调试什么。我知道Java不仅需要堆(因此需要进行本机内存跟踪),但是jvm本机内存跟踪器报告的内容与docker stats所看到的之间仍然存在约150m的差距。我如何才能获得有关内存运行方向的更多见解?
答案 0 :(得分:1)
JVM报告的内存不足。
JVM的内存占用量
那么,什么导致JVM内存占用呢?我们大多数人 运行Java应用程序,知道如何设置最大堆空间。但 实际上,对内存占用的贡献更多:
- 本地JRE
- 烫发/元空间
- JIT字节码
- JNI
- NIO
- 线程
当我们要设置内存时,需要记住很多 Docker容器的限制。并设置容器内存 限制到最大堆空间,可能还不够……
JVM和CPU
让我们简要了解一下JVM如何调整到 在其运行的节点上可用的处理器/核。有 实际上,许多参数默认情况下是基于初始化的 在核心数量上。
- ♯个JIT编译器线程
- ♯垃圾回收线程
公用fork-join池中的线程的- ♯ …
因此,如果JVM在32核心节点上运行(并且其中一个没有覆盖 默认),JVM将产生32个垃圾回收线程,32个JIT 编译器线程,…。 source
要尽可能地避免此问题,您应该使用+UseContainerSupport
(自Java 10中默认启用8u191以来可用),并且可能取决于您观察到的总已使用内存,而-XX:MaxRAMPercentage=90.0
或更小。有关更多信息,请参见this和that。
我强烈推荐:"Nobody puts Java in the container: Ken Sipe"来自JavaZone
答案 1 :(得分:0)
A。请仔细阅读janisz的答案,并点击链接,对于在容器中或在cgroup下使用Java的人来说,它是非常重要的信息。
B。主要问题是JVM没有看到容器的内存限制:它认为它具有主机OS的全部可用内存。当它尝试消耗超过cgroup限制所允许的内存时,内核/ docker会因为违反cgroup内存限制承诺而杀死该容器。 -XX:+UseContainerSupport
和较旧的-XX:+UseCGroupMemoryLimitForHeap
标志应该可以解决:让JVM知道真正的限制是什么。
-Xmx
标志并没有限制JVM(作为Linux进程)需要操作系统提供的所有内存。 JVM本身的所有功能,包括Java堆栈,元空间,已加载的代码等(如janisz的答案所述)的确也占用内存空间。
不幸的是,JVM喜欢从操作系统中获取所需的尽可能多的内存,并且更喜欢占用更多的内存(如果认为可用),然后重用现有的(可能是可释放的)内存。作为Java 12附带的新G1 garbage collector的一部分,计划对此行为进行改进(即不假设JVM是系统中唯一的参与者),但是除非您为此工作,否则JVM将始终在增长在内存使用方面,并且会优先使用所有可用的空闲内存,前提是操作系统的唯一目的是为其运行的这个JVM提供服务。