java - 为什么调用 System.gc() 会导致内存使用量显着减少?

标签 java spring memory-management memory-leaks jvm

我有一个长时间运行的 JVM Spring 服务器应用程序,它会进行连续处理。我注意到内存使用量随着时间的推移逐渐增加,但它永远不会导致 JVM 内存不足崩溃。但是,当我手动生成堆转储时,我观察到内存使用量显着下降,返回到最初预期的水平。当我分析转储时,我没有看到任何异常,因为转储可能是用垃圾收集内存生成的。据我所知,发生这种下降是因为生成堆转储会触发垃圾收集器工作。

为了测试此行为,我尝试调用 System.gc(),它重现了内存下降。我很好奇为什么会发生这种情况。 为什么 JVM 不自动执行垃圾回收? 看来,出于某种原因,如果我没有明确强制清除它,它就不会这样做。但正如我提到的,这不会导致 JVM 崩溃。也许它会在需要时释放该内存。 这是一个在 Kubernetes 上运行的自动缩放应用程序,此行为会导致由于内存增加而不必要地创建额外实例。

是否有一个参数可以传递给与此行为相关的 JVM?

我希望 JVM 自动清除内存,而无需我显式调用 System.gc()

最佳答案

Why does JVM not perform this garbage collection automatically?

Java 确实自行决定自动运行垃圾收集器。执行此操作的时间和效果取决于许多因素,并且并非所有 GC 运行都是相同的。除此之外,收集无法访问的对象可以为虚拟机提供更多可用内存,但从操作系统的角度来看,这并不一定会减少虚拟机的内存使用量。

从操作系统的角度来看,通过 System.gc() 手动请求 GC 也不一定会减少 VM 的内存使用量。事实上,its docs不做出具体 promise ,并明确否认以下几点:

When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all unused objects. There is no guarantee that this effort will recycle any particular number of unused objects, reclaim any particular amount of space, or complete at any particular time, if at all, before the method returns or ever. There is also no guarantee that this effort will determine the change of reachability in any particular number of objects, or that any particular number of Reference objects will be cleared and enqueued.

你接着说,

This is an autoscaling application running on Kubernetes, and this behavior results in the unnecessary creation of additional instances due to the memory increase.

Is there a parameter which i can pass to JVM related to this behaviour?

这是您的特定虚拟机的功能。没有与该问题相关的标准 VM 选项,但您的特定 VM 可能具有影响 GC 策略和计时的选项,并且可能有一些选项会影响 VM 将使用的内存总量。您应该查看您的虚拟机的文档以获取更多信息。

如果您碰巧使用 Oracle/OpenJDK VM,那么您会对 Oracle 相当广泛的 GC 调优文档感兴趣。选择适用于您的特定 VM 版本的文档版本。例如,如果您使用的是 Java 21,那么您正在寻找 https://docs.oracle.com/en/java/javase/21/gctuning/introduction-garbage-collection-tuning.html#GUID-326EB4CF-8C8C-4267-8355-21AB04F0D304 .

关于java - 为什么调用 System.gc() 会导致内存使用量显着减少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77438952/

相关文章:

部署 Tomcat 后 Java/Spring 应用卡住

两个事件之间的 Java 堆分析

具有多个数据库驱动程序的 Java Spring Boot 应用程序无法在 Linux 上运行

java - 锁定一个简单的并发 HashMap

java - 无法在 Mac High Sierra 上打开 UIAutomatorviewer

java - 左加入 spring data jpa 和 querydsl

java - 卡在 springcontext.xml 中

c++ - 类成员和成员函数内存位置

objective-c - @"Strings"在内存中是如何分配的?

java - BaseGameUtils GoogleApiClient.ApiOptions 无法解析为类型