【发布时间】:2025-12-06 11:10:01
【问题描述】:
我们的应用程序中有一个 Java Micorservice,它连接到 Postgres 和 Phoenix。我们使用的是 Spring Boot 2.x。
问题是我们正在为我们的应用程序执行大约 8 小时的耐久性测试,我们可以观察到使用的堆在不断增加,尽管我们使用了推荐的 VM 参数建议,看起来像是内存泄漏。我们分析了堆转储,但根本原因对我们来说并不完全清楚,一些专家可以根据结果提供帮助吗?
我们实际使用的虚拟机参数是:
-XX:ConcGCThreads=8 -XX:+DisableExplicitGC -XX:InitialHeapSize=536870912 -XX:InitiatingHeapOccupancyPercent=45 -XX:MaxGCPauseMillis=1000 -XX:MaxHeapFreeRatio=70 -XX:MaxHeapSize=536870912 -XX:MinHeapFreeRatio=40 -XX:ParallelGCThreads=16 -XX:+PrintAdaptiveSizePolicy -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:StringDeduplicationAgeThreshold=1 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX: +UseG1GC -XX:+UseStringDeduplication
我们预计 GC 日志中使用的堆应该是平坦的,但是内存消耗并没有释放,并且还在不断增加。
【问题讨论】:
-
“我们使用了 VM 参数的推荐建议”谁根据什么理由向您推荐了这些参数?他们是否说“这些是使每个应用程序运行得比默认设置更好的神奇参数”?但无论如何,只要你没有遇到
OutOfMemoryError,就没有理由假设存在内存泄漏。事实上,没有这样的错误证明“使用的堆在不断增加”。 -
感谢您的意见,这些不是任何专家推荐的建议,但根据我们的多次运行和观察以及文档中提供的定义,我们得出结论,这应该是我们可以使用适当的组合来更好地执行。
-
您还说“没有理由假设存在内存泄漏”。但是,如果我们继续执行 24 小时并且使用的堆正向顶部移动,是否会有一段时间达到其最大限制和完全 GC 的机会。我们还观察到(在不同的运行中)即使在完全 GC 之后也只有部分堆内存被释放。现在有内存不足的可能吗?
-
一些内存被永久分配,一些内存被分配和释放是正常的行为。这并不排除永久分配的内存包含一些您不想保留的对象,但只要永久分配的内存没有上升到应用程序失败的程度(例如使用
OutOfMemoryError),您没有严重的问题。而且我们无法从内存统计中看到是否有不需要的对象。甚至堆转储(更不用说屏幕截图)也无济于事,因为我们不知道哪些对象应该存在,哪些不存在。 -
非常感谢 Holger,我们现在可以使用 IHOP 和 Newratio 获得一个不错的 GC 图。使用的堆比以前更好地释放。
标签: garbage-collection jvm heap-memory