您可以通过调用System.gc()
在Java中进行垃圾回收,但有时会导致应用程序“停滞”。像这样进行垃圾回收并避免停滞是否是一个不好的主意:
new Thread(new Runnable() {
public void run() {
System.gc();
}
}).start();
或者这会导致更多的问题吗?
您可以通过调用System.gc()
在Java中进行垃圾回收,但有时会导致应用程序“停滞”。像这样进行垃圾回收并避免停滞是否是一个不好的主意:
new Thread(new Runnable() {
public void run() {
System.gc();
}
}).start();
除非你有一个非常好的理由。即使你认为有理由这样做,你可能也没有。
如果你继续阅读,我假设你有一个真正好的(尽管可能扭曲的)理由来试图捣鬼GC,即使它在确定何时收集内存方面比你更聪明是非常有可能的。此外,请记住,显式地调用它会让它感到困惑并破坏它的启发式算法,因此它变得比以前更不聪明了,所有这些都是因为你试图超越它。
如果你有非常好的理由这样做,或者在你真正想确保在最佳内存状态下开始进行密集代码段的情况下,你需要知道这可能行不通:对System.gc()
的调用不能保证垃圾回收将发生,如在其Javadoc中提到(我的强调):
调用gc方法建议Java虚拟机花费努力回收未使用的对象。
-XX:+DisableExplicitGC
(如果您的JVM支持它),以防止那些疯狂的调用对系统造成任何伤害(感谢评论区中的Fredrik)grep
查找对System.gc()
及其等效方法的调用,并摆脱它们。请参阅Grooveek's answer获取其他有用的建议(例如使用WeakReference
)。
根据您的用例,可能尝试其他GC实现会有所帮助:CMC、G1、ParallelGC等。如果您想避免“停顿”,自Java SE 6更新以来,我一直在最新的Java 7版本中使用G1取得了非常好的结果,长时间运行密集型企业应用程序。
只需注意,JVM调优是一门非常复杂的艺术。
您可以翻阅这些内容以获取更多细节:
* 谨慎使用:有时不是完全最新的,没有记录所有内容,并列出了许多实验性功能或仅限于HotSpot的功能。
是的,大多数时候调用System.gc()是一个非常糟糕的想法。虽然也有例外情况,但它们很少见,主要还是花时间确保你不做会影响垃圾回收性能的事情,并学习并确保你理解如何进行垃圾回收,而不是通过显式调用System.gc()来自己处理。
Calling the gc method suggests that the Java Virtual Machine expend effort toward
recycling unused objects in order to make the memory they currently occupy available
for quick reuse. When control returns from the method call, the Java Virtual Machine
has made a best effort to reclaim space from all discarded objects.
我完全同意通常不建议显式调用垃圾回收器。它可能会使应用程序停顿几秒钟,甚至几分钟。如果您正在处理后台服务,则通常不是问题,但如果暴露给用户,则会导致不良体验。
然而,在极端情况下,当内存非常短缺且应用程序可能崩溃时,您将希望这样做。但是,在应用程序的设计和实现中可以采取很多措施来避免这些情况。
Java 中一个我喜欢的功能是WeakReference对象,它们可以回收内存并避免内存泄漏。它们是您的好朋友。
正如其他人所说,调用System.gc()
通常是一个错误。(并非总是如此...)
假设您有其中一种罕见的用例,调用System.gc()
可能会有益处,则有两种情况需要考虑:
如果您的JVM正在使用经典的“停止所有线程”收集器,则在单独的线程中运行它不会有任何区别。GC会在整个过程中停止所有应用程序线程。
如果您的JVM正在运行并发收集器,则在单独的线程中运行它可能是一个好主意。虽然所有收集器都有一个阶段,在该阶段中停止所有线程,但是调用System.gc()
被记录为在“Java虚拟机已尽最大努力从所有丢弃的对象中回收空间之后”返回。因此,在单独的线程中运行它将允许当前线程执行其他操作。但是,您需要小心,避免启动多个线程,每个线程都调用System.gc()
;即负责启动线程的代码需要跟踪任何先前的GC线程。
System.gc()
?你了解是什么导致了这些停顿(顺便说一下,并非所有GC都有这种停顿)?如果是,稍微思考一下就能回答你的问题。如果不了解,你应该在尝试超越它们之前,先提高对GC和现代JVM的理解。 - user395760