关于java:强制JVM释放内存

Force JVM to free memory

我改进了代码以从垃圾收集器中获得更好的结果。

现在,当我调用 System.gc() 时,它确实释放了所有内存。但是当我在不调用 System.gc() 的情况下观察内存使用情况时,应用程序确实会保留并使用越来越多的内存。

这是否意味着我的改进正在发挥作用,并且我的所有引用都正确,我可以忽略 JVM 如何自行释放内存。或者我的代码中是否还有其他问题是 JVM 在不运行垃圾收集器的情况下保留更多内存的原因。


取决于你的 JVM 使用的是哪个 GC。
如果是 JDK9,那么它可能是 G1,它在内存消耗方面是"贪婪的",
因此,根据您检查内存使用的方式,它可能看起来好像占用了大量内存(因为这是保留它并动态/按需使用/释放。

你可以使用

https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jstat.html

检查内存消耗。

关于 GC 和内存消耗分析,请查看以下内容:
G1 垃圾收集器的高内存使用问题

https://www.javacodegeeks.com/2017/11/minimize-java-memory-usage-right-garbage-collector.html


未使用的内存是浪费的内存。

为什么要显式调用System.gc()。恕我直言,您永远不应该调用它并让 JVM 来决定何时运行 GC。 (如果您是新手,JVM 可以做出比您更好的决定。仅当您真正知道自己在做什么时才调用 System.gc()。)调用 System.gc().

通常是一种不好的做法

System.gc() 只是对 JVM 运行 GC 的请求/提示。这绝不意味着 GC 肯定会运行。

你可以在 Java 中出现内存泄漏,但这肯定不是你的情况要考虑的事情,因为正如你在调用 System.gc() 时提到的那样,你可以看到一些内存被释放。 (因此,您不会仍然持有未使用对象的引用,这会阻止 GC 清理这些对象。)

为什么您认为您的代码有问题?可能不需要更多内存,或者如果需要内存,你已经有足够的内存了(用外行的话来说,GC 不会释放内存,因为程序还有很多东西可以运行 -那么GC为什么要清理内存呢?)。


当然,您有可能存在内存泄漏,这意味着您的程序一直在分配内存而从未释放它。 (例如,在不断增长的列表或地图中。)您将需要一个内存分析器来确保您不会遇到这种情况。

除此之外,如果虚拟机似乎一直在分配内存而不释放它,我不会担心。这就是现代 VM 的工作方式,尤其是在"客户端"模式下:只要有足够的可用内存,它们就不会浪费时间进行垃圾收集。如果接近内存限制,那么垃圾收集器就会启动。 ("客户端"与"服务器"模式是一个 JVM 参数,如果需要,您可以尝试使用它,更多信息在这里:"java -server"和"java -client"之间的真正区别?)

除此之外,你可以做的是:

a) 确保执行完整 GC 的机制实际上是执行完整 GC。我所知道的最好的机制(不能保证有效,但据我所知它似乎有效)是分配一个仅通过软引用引用的对象,然后继续调用 GC 直到软引用变为 null .

b) 在调试运行时(例如,如果启用了断言),每隔几秒就会在单独的线程上触发一次完整的 GC。然后,如果您查看 VM 消耗的内存,它应该大致保持不变。如果没有,你有内存泄漏。


没有办法强制JVM释放内存,System.gc()只是一个提示。由 GC 来管理内存(请注意有各种类型的内存,例如堆、元空间、堆外)。每个 GC 算法都有多个可以调整的配置参数,但它们都不会给您提供按需释放内存的选项。

JVM 在启动时保留内存并向操作系统请求额外的内存,直到达到配置的任何限制。它以块增量的方式执行此操作,一次请求 MB 或更多内存,因为从 OS 逐字节请求内存效率非常低。