System.gc()什么时候做任何事情

时间:2020-03-05 18:54:25  来源:igfitidea点击:

我知道垃圾回收在Java中是自动化的。但是我知道,如果我们在代码中编写" System.gc()",那么Java VM可能会或者可能不会在运行时决定在此时进行垃圾回收。这是如何工作的? VM看到" System.gc()"时会根据什么基础/参数准确地决定执行(或者不执行)GC?在这种情况下,最好有一些示例将其放入代码中?

解决方案

回答

实际上,它通常决定进行垃圾回收。答案因许多因素而异,例如我们正在运行的JVM,它所处的模式以及所使用的垃圾收集算法。

我不会在代码中依赖它。如果JVM即将抛出OutOfMemoryError,则调用System.gc()不会停止它,因为垃圾收集器将尽最大努力释放它,直到达到极限。我唯一看到它是在实践中使用的,这是在IDE中将其添加到用户可以单击的按钮上的,但是即使在那儿它也不是很有用。

回答

System.gc()由VM实现,它的作用是特定于实现的。例如,实现者可以简单地返回而不做任何事情。

至于何时发出手动收款,我们唯一想做的就是我们放弃包含大量较小收款的大型收款时,
例如" Map <String,<LinkedList >>" -并且我们想尝试在当时和那里获得最佳性能,但是在大多数情况下,我们不必为此担心。不幸的是,GC多数时候都比我们更了解。

回答

我们无法通过Java中的GC进行控制-VM决定。我从未遇到过需要System.gc()的情况。由于System.gc()只是简单地建议VM进行垃圾收集,并且它也进行FULL垃圾收集(多代堆中的旧世代和新世代),因此实际上可能导致更多的CPU周期消耗超过必要。

在某些情况下,可能会建议VM立即进行完整收集,因为我们可能知道应用程序将在接下来的几分钟内处于空闲状态,然后再进行繁重的操作。例如,在应用程序启动期间初始化了许多临时对象之后(即,我只是缓存了一堆信息,并且我知道一分钟左右不会有太多活动)。考虑一下诸如eclipse启动之类的IDE,它进行了大量的初始化工作,因此也许在初始化之后立即在此时进行完整的gc有意义。

回答

简而言之:

参数取决于VM。

用法示例无法为运行时/生产应用程序想到一个示例,但对于某些分析工具(例如调用)运行它很有用

// test run #1
test();
for (int i=0; i<10; i++) { 
// calling repeatedly to increase chances of a clean-up
  System.gc(); 
}
// test run #2
test();

回答

我想不出一个具体的示例来运行显式GC很好。

通常,运行显式GC实际上会带来弊大于利,因为显式gc会触发完整的收集,而收集通过每个对象所花费的时间会更长。如果此显式gc最终被重复调用,则可能会导致应用程序运行缓慢,因为花费大量时间运行完整的GC。

另外,如果使用堆分析器检查堆,并且怀疑库组件正在调用显式GC,则可以将其关闭,方法是:在JVM参数中添加gc = -XX:+ DisableExplicitGC。

回答

如果调用System.gc(),则需要非常小心。调用它可能会给应用程序增加不必要的性能问题,并且不能保证实际执行收集。实际上,可以通过java参数-XX:+ DisableExplicitGC禁用显式的System.gc()。

我强烈建议我们阅读Java HotSpot Garbage Collection中提供的文档,以获取有关垃圾收集的更多详细信息。

回答

我可以想到的唯一示例是在分析应用程序以搜索可能的内存泄漏时调用System.gc()的意义。我相信分析器会在拍摄内存快照之前调用此方法。

回答

大多数JVM都会启动GC(取决于-XX:DiableExplicitGC和-XX:+ ExplicitGCInvokesConcurrent开关)。但是,规范的定义不太明确,以便以后可以更好地实现。

规范需要澄清:错误#6668279 :(规范)System.gc()应该表明我们不建议使用也不保证行为

RMI和NIO在内部使用gc方法,它们需要同步执行,这是:目前正在讨论中:

错误#5025281:允许System.gc()触发并发(而不是世界停止)的完整集合

回答

通常,VM会在引发OutOfMemoryException之前自动进行垃圾回收,因此添加显式调用无济于事,除非它可能将性能降低的时间提前。

但是,我认为我遇到了一个可能与之相关的案例。不过我不确定,因为我还没有测试它是否有效果:

当我们对文件进行内存映射时,我相信当没有足够大的内存块时map()调用会引发IOException。我认为,map()文件之前的垃圾回收可能有助于防止这种情况的发生。你怎么认为?

回答

如果我们使用直接内存缓冲区,那么即使直接内存不足,JVM也不会为我们运行GC。

如果调用ByteBuffer.allocateDirect()并收到OutOfMemoryError,则可以发现在手动触发GC后此调用是正确的。

回答

我们永远不能强迫垃圾收集。 System.gc只是建议使用vm进行垃圾回收,但是,实际上该机制何时运行,没人知道,这是JSR规范所指出的。