Java内存使用率远高于堆+非堆

Pet*_*ter 6 java memory heap-memory docker spring-boot

我有一个带有 SpringBoot 版本 2.1.1.RELEASE 的 Java 应用程序(oracle JDK 8u191),我遇到了奇怪的内存使用情况(不认为这与 spring 相关)。

应用程序提供的 HEAP 和 NONHEAP 值的总和远低于 Docker 报告的实际内存使用情况。

我知道 Java 具有除 HEAP 和 NONHEAP 之外的其他内存区域,但我不知道如何衡量它们以及当前行为是否正常。

目前,我的应用程序报告以下内容(在生产中运行 3 天后):

           Init       Used       Committed       Max       
HEAP:      250M       79M        250M            800M      
NONHEAP:   2M         192M       201M            0M     
Run Code Online (Sandbox Code Playgroud)

/metricsspringBoot的执行器端点报告相同的内存使用情况。

但是 docker stats 命令报告了这一点(容器内部smem报告了与 java 进程相同的值):

MEM USAGE / LIMIT
750.2MiB / 1.172GiB
Run Code Online (Sandbox Code Playgroud)

堆+非堆和当前使用的内存的区别是299,2mb

在我们第一次将这项服务投入生产时,我没想到会有 300mb,这导致了很多 OOM,直到我们找到了正确的配置。

即使在 GC 之后,这种“未注册的内存使用量”似乎只会增加而不会减少。

如果我重新启动应用程序,堆+非堆与实际使用之间的差异约为 100mb。

我的 Dockerfile 以这种方式启动应用程序:

ENTRYPOINT ["java", "-Xms250m", "-Xmx800m", "-XX:+UseG1GC", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"]

我还有一个计划的 rotine,它System.gc()每小时运行一次以缩减提交的内存,因为该服务在一天内有小高峰,我希望未使用的内存可用于其他服务。

我想知道这种行为是否正常。我如何衡量使用这么多内存的内容?visualvm 和 jconsole 只显示堆和非堆。似乎 springBoot 执行器中也没有度量标准来衡量这一点。

对于这种类型的使用,我应该在容器中保留多少内存?我找不到任何关于它的有用文章。

编辑1:

7 天后,(heap+nonheap)-total 之间的差异变成了 550mb,让我的容器没有任何内存。

编辑2:

深入研究这篇文章后,事情开始变得有意义:

Java进程内存使用与jcmd提交内存的偏差

这些java本机内存是从哪里分配的?

Java 进程内存使用情况(jcmd vs pmap)

事实上,我们正在使用带有内存泄漏报告的第三方库: compile("axis:axis-wsdl4j:1.5.1")

我会尝试升级到 Axis2 并将结果发布在这里。