首页 > 解决方案 > 年老代垃圾收集未清除

问题描述

我有一个 java spring boot 项目。当执行与多线程(Executor 服务)相关的代码时,内存会被填满。GC 并未清除此内存。阅读 GC 文档后,才知道终身内存没有被清除。通过使用 Java Profiler 监控 JVM,我注意到这个 Tenured Generation 永远不会被清除(直到满,就我而言)。

  1. 我怎样才能让 gc 清除终身空间?

我们使用 docker image 运行应用程序

标签: javaspringmultithreadingspring-bootgarbage-collection

解决方案


这里有两个潜在的问题。

  1. 垃圾收集器,只能释放不可访问的对象。因此,如果永久对象仍然可以访问,它们将永远不会被释放。这是一个内存泄漏场景。

  2. JVM 可能没有运行旧/终身空间收集,因为它不需要. JVM 通常只会在它认为有必要/经济的时候运行旧的空间收集器。这实际上是一件好事,因为大多数容易(廉价)收集的垃圾通常都在新空间中。


阅读 gc 文档后,才知道终身内存没有被清除。

这可能是对文档的误读。GC 将收集永久空间中的对象。它应该发生在您开始获得 OOME 之前。


如何让 GC 清除永久空间?

您可以调用System.gc()... 这给 JVM 一个提示,即现在运行 GC 将是一件好事。然而:

  • 这只是一个提示。JVM 可能会忽略它。
  • 它可能会或可能不会运行旧空间集合。
  • 它不会“清除”老一代。它甚至不一定会释放所有无法访问的对象。
  • 调用通常是低效System.gc()的。JVM 通常对运行 GC 的最有效时间以及运行哪种 GC 有更好的了解。
  • 运行 GC可能实际上并不会释放内存供系统的其余部分使用。

简而言之,调用System.gc(). 在大多数情况下,它什么也做不了。

如果您的真正问题是内存泄漏,它肯定会有所帮助。如果您正在获得 OOME,那将无济于事。


推荐阅读