java - Java内存使用率远高于heap+nonheap
问题描述
我有一个带有 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
springBoot的执行器端点/metrics
报告相同的内存使用情况。
但是 docker stats 命令会报告这一点(在容器内smem
报告 java 进程的值相同):
MEM USAGE / LIMIT
750.2MiB / 1.172GiB
heap+nonheap 和当前使用的内存的区别是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:
深入研究这篇文章后,事情开始变得有意义:
事实上,我们正在使用第三方库报告内存泄漏:compile("axis:axis-wsdl4j:1.5.1")
我会尝试升级到 Axis2 并将结果发布在这里。
解决方案
推荐阅读
- python - Flask 无法在 PHP 中运行
- django - Django-Filter:外键字段上的多个 select2 选择
- javascript - 在 javascript 函数中找出一组 json 数据?
- python - 试图从 *.npy 文件制作数据集。无法将 NumPy 数组转换为张量
- shell - 创建指定 Tmux 窗格的脚本
- swift - 需要帮助使用 AVAssetExportSession 导出音频
- swiftui - 如何创建类似抽屉(滑出)的动画?
- flutter - 如何在 Flutter 中从 CurvedNavigationBar 中的子项更改页面
- url-rewriting - 同一 URL 中的多个重写规则
- mysql - Apache Airflow 需要 MySQL 服务器中的 explicit_defaults_for_timestamp 标志