为什么即使对于开箱即用的Spring Boot管理员来说,RES内存对于Java进程来说仍然保持缓慢增长?

问题描述

我在一台32GB的计算机上运行23个Java进程。没有任何进程指定JVM内存参数,例如Xmx。 java -XX:+PrintFlagsFinal -version | grep MaxHeapSize报告说,最大认堆大小为预期的8GB。

每个进程都运行嵌入式Tomcat(Spring Boot应用程序(大多数版本为2.3.4)),除了一个是运行三个WAR的独立tomcat 9实例。这些应用的使用率较低(通常一天使用一个用户,每天使用10分钟)。它们不占用内存或cpu。其中一个是Spring Boot管理员,另一个是Spring Cloud的Eureka服务注册表。对于这两个,我只有一个主要方法可以简单地引导Spring Boot应用程序。

但是,RES的内存(如每个进程的顶部所示)一直在逐渐增加。例如,在过去12小时内,Spring Boot服务注册表已从1.1GB增加到1.5GB。所有进程的RES都有类似的小幅增长,​​但是在同一12小时内,总增长将可用内存减少了2 GB。在之前的12小时(以此类推)中,情况一直如此,直到目前的可用内存只有4.7GB。

我担心的是,我仍然会看到这种趋势(即使没有使用应用程序)。永远不会从应用程序中释放内存,因此总可用内存继续减少。这是正常的,因为也许每个JVM都认为操作系统中的内存仍然可用,并且有8GB的堆空间可供使用?一旦达到操作系统可用内存阈值,JVM会在某个时候停止占用内存吗?还是会一直持续到所有可用内存都用完?

更新

大多数应用程序使用的堆小于200MB,但堆大小为1.5-2.8GB。堆最大为8GB。

解决方法

操作系统报告的常驻内存不会告诉您正在消耗什么组件。您必须收集其他数据才能确定过程的哪个部分正在增长

您必须进行跟踪

  • java堆和元空间的使用-您可以使用JMC,gc日志记录和许多其他Java监视工具对其进行监视
  • jvm堆外使用-NMT
  • 直接字节缓冲区的使用-MX beans,也可以通过JMC获得
  • 按映射文件使用-pmap -x <pid>
  • 由本机库使用,例如通过JNI使用-难以监视
,

我也遇到过这种情况,经过长时间的研究,我找到了解决方案 here。基本上,就我而言,这只是在 jar 调用上设置 xms 和 xmx 参数的问题,从而迫使 GC 不断采取行动。