-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
在此期间,JVM统计数据保持正常
所以我不知道我还可以在JVM端调试什么。我了解java需要的不仅仅是堆(因此本机内存跟踪),但在jvm本机内存跟踪器报告的内容和docker统计数据所看到的内容之间仍然有大约150m的差距。我如何在内存的去向中获得更多见解?
答:请仔细阅读janisz的答案,并遵循链接,对于在容器中或在cGroup下使用Java的人来说,这是很多非常重要的信息。
B.主要问题是JVM没有看到容器上的内存限制:它认为自己拥有主机操作系统的全部可用内存。当内核/docker试图消耗超过cgroup限制所允许的内存时,内核/docker会因违反cgroup内存限制promise而杀死容器。这就是-XX:UseContainerSupport
和较早的-XX:UseCGroupMemoryLimitForHeap
标志应该解决的问题:让JVM知道真正的限制是什么。
-Xmx
标志并不限制JVM(作为Linux进程)从操作系统需要的所有内存。JVM本身的所有机制,包括Java堆栈、元空间、加载的代码等(正如janisz在回答中所讨论的),都会占用内存空间。
不幸的是,JVM喜欢从操作系统中获取所需的内存,并且更喜欢获取更多内存(如果它认为可用),然后重用现有的(可能是可释放的)内存。对这种行为的改进(即,不假设JVM是系统中唯一的参与者)计划作为Java 12附带的新G1垃圾收集器的一部分,但除非您有这样的功能,否则JVM的内存使用量将始终增加,并倾向于消耗所有可用的空闲内存,假设操作系统的唯一目的是为它正在运行的JVM提供服务。
JVM报告的内存不是一切。
那么,是什么导致了JVM内存占用?我们大多数运行过Java应用程序的人都知道如何设置最大堆空间。但实际上,对内存占用的影响要大得多:
当我们想要使用Docker容器设置内存限制时,需要记住很多。并且将容器内存限制设置为最大堆空间可能还不够...
让我们简要介绍一下JVM是如何根据其运行的节点上可用的处理器/内核数量进行调整的。实际上有很多参数,默认情况下是基于核心计数初始化的。
因此,如果JVM在32核节点上运行(其中一个没有覆盖默认值),JVM将生成32个垃圾收集线程、32个JIT编译器线程等等…。来源
为了防止这个问题,您应该使用UseContainerSupport
(在Java 10中默认启用8u191后可用),并且可能使用-XX:MaxRAMPercentage=90.0
或更少,具体取决于您观察到的总使用内存。要了解更多信息,请查看这个和那个。
我强烈推荐:"没有人把Java放在容器里:Ken Sipe"来自JavaZone
我正在调试一个Azure Web应用程序上无法解释的内存消耗。我花了很多时间使用dotmemory、perfview和诊断工具挖掘日志、内存转储,但仍然无法理解为什么我们的应用程序内存一整天都在稳步增长。 我在堆中验证了多次,以确保请求前后的应用程序对象/模块都被释放,上面的屏幕截图显示了这一点。 如果你能分享一些关于如何找到消耗内存的东西的建议,我会的
问题内容: 我是Go的新手,它试图弄清楚它如何管理内存消耗。 我在一个测试项目中的内存出现问题。我不明白为什么当我的程序长时间运行时,Go使用越来越多的内存(从不释放它)。 我正在运行下面提供的测试用例。第一次分配后,程序将使用近350 MB的内存(根据ActivityMonitor)。然后,我尝试释放它,ActivityMonitor显示内存消耗增加了一倍。为什么? 我正在使用Go 1.0.3在
问题内容: 我需要监视应用程序产生的线程消耗的内存量。如果贪婪的线程消耗太多内存,则想法是采取纠正措施。我已提到Java线程占用多少内存?。关于该链接的建议之一是在我尝试以下工作时使用。 我在四个线程上运行了很长时间。尽管作业不会连续地累积内存,但是所返回的值会不断增加,甚至不会下降。这意味着不会返回线程使用的堆上的实际内存量。它返回自线程启动以来在堆上为线程分配的内存总量。我的平台详细信息如下:
我需要监控应用程序生成的线程所消耗的内存量。如果贪婪的线程占用了太多内存,那么我们可以采取纠正措施。我提到了我的java线程需要多少内存?。关于该链接的建议之一是在ThreadMXBean中使用getThreadAllocatedBytes 我用以下作业试验了getThreadAllocatedBytes。 我在四个线程上运行了相当长的时间。虽然作业不会连续累积内存,但getThreadAlloc
关于Java应用程序使用的驻留内存,我有两个问题。 一些背景细节: 我用-xms2560m-xmx2560m设置了一个java应用程序。 java应用程序在容器中运行。k8s允许容器最多消耗4GB. 堆:应用程序的工作方式似乎是使用所有内存,然后释放,然后使用等等。 这张快照说明了这一点。Y列是空闲堆内存。(由应用程序通过)提取) 我还可以使用HotSpotDiagnosticMXBean来确认它
我有一个很小的java控制台应用程序,我想在内存使用方面进行优化。它是在Xmx设置为仅64MB的情况下运行的。根据不同的监视工具(htop、ps、pmap、Dynatrace)显示进程的总体内存使用量超过250MB。我主要在Ubuntu18上运行它(也在其他操作系统上测试)。 我使用了-xx:nativeMemoryTracking,java param和jcmd的本地内存跟踪,以找出为什么在堆之