it-swarm.cn

System.gc()什么时候做什么

我知道垃圾收集在Java中是自动化的。但我明白,如果你在代码中编写System.gc(),那么Java VM可能会或者可能不会在运行时决定在那时进行垃圾收集。这是如何工作的? VM在看到System.gc()时决定做(或不做)GC的基础/参数是什么?是否有一些例子,在这种情况下它一个好主意把它放在你的代码中?

106
harry

在实践中,它 通常 决定进行垃圾收集。答案取决于很多因素,例如您正在运行的JVM,它所处的模式以及它正在使用的垃圾收集算法。

我不会在你的代码中依赖它。如果JVM即将抛出OutOfMemoryError,则调用System.gc()将不会停止它,因为垃圾收集器将在它进入极端之前尝试尽可能多地释放它。我在实践中看到它的唯一一次是在IDE中,它附加到用户可以点击的按钮,但即便如此,它也不是非常有用。

55
jodonnell

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

28
Guillermo Vasconcelos

您无法控制Java中的GC - VM决定。我从来没遇到System.gc() 需要 的情况。由于System.gc()调用只是假装VM执行垃圾收集并且它还执行完全垃圾收集(多代堆中的新旧代),然后它实际上可以导致 _更多_ cpu循环消耗超过必要的。

在某些情况下,向VM建议它现在可以完整收集可能是有意义的,因为您可能知道应用程序在繁重提升之前将在接下来的几分钟内处于空闲状态。例如,在应用程序启动期间初始化大量临时对象之后(即,我刚刚缓存了一大堆信息,我知道我将在一分钟左右没有获得太多活动)。想想一个IDE,比如Eclipse启动 - 它做了很多初始化,所以也许在初始化之后立即做一个完整的gc是有意义的。

24
DustinB

当您调用System.gc()时,Java语言规范不保证JVM将启动GC。这就是为什么“可能会或可能不会决定在那时做GC”。

现在,如果你看一下 OpenJDK源代码 ,这是Oracle JVM的主干,你会看到对System.gc()的调用确实启动了一个GC循环。如果您使用其他JVM,例如J9,则必须检查其文档以找出答案。例如,Azul的JVM有一个连续运行的垃圾收集器,因此调用System.gc()将不会执行任何操作

其他一些答案提到在JConsole或VisualVM中启动GC。基本上,这些工具可以远程调用System.gc()

通常,您不希望从代码中启动垃圾回收周期,因为它会混淆应用程序的语义。你的应用程序做了一些业务,JVM负责内存管理。您应该将这些问题分开(不要让您的应用程序进行一些内存管理,专注于业务)。

但是,很少有人可以理解对System.gc()的调用。例如,考虑微基准测试。没有人希望在微基准测试的中间发生GC循环。因此,您可以在每次测量之间触发GC循环,以确保每个测量都以空堆开始。

22
Pierre Laporte

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

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

17
David Schlosnagle

System.gc()由VM实现,它的功能是特定于实现的。例如,实施者可以简单地返回并且什么都不做。

至于何时发布手动收集,只有当你放弃包含大量较小集合的大型集合时才会这样做 - 例如Map<String,<LinkedList>> - 并且你想尝试获取性能指数然后在那里,但在大多数情况下,你不应该担心它。 GC比你更清楚 - 很遗憾 - 大多数时候。

10
Patrick

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

如果你调用ByteBuffer.allocateDirect()并得到一个OutOfMemoryError,你可以在手动触发GC后找到这个调用。

8
Peter Lawrey

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

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

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

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

3
eckes

Garbage CollectionJava中很好,如果我们在Desktop/laptop/server中执行用Java编码的软件。你可以在Java中调用System.gc()Runtime.getRuntime().gc()

请注意,这些电话都不能保证做任何事情。它们只是jvm运行垃圾收集器的建议。无论是否运行GC,它都在JVM上。所以,简短回答:我们不知道它何时运行。更长的答案:如果有时间,JVM会运行gc。

我相信,这同样适用于Android。但是,这可能会降低您的系统速度。

2
Naveen

我们永远不能强制垃圾收集。 System.gc只是建议垃圾收集的vm,但是,实际上机制运行的时间,没有人知道,这是JSR规范所述。

2
lwpro2

在花时间测试各种垃圾收集设置方面有很多话要说,但如上所述,这样做通常没有用。

我目前正在开发一个涉及内存限制环境和相对大量数据的项目 - 有一些大数据可以将我的环境推向极限,即使我能够降低内存使用率理论上它应该工作得很好,我仍然会得到堆空间错误---详细的GC选项告诉我它正在尝试垃圾收集,但无济于事。在调试器中,我可以执行System.gc(),并且肯定会有“足够”的内存可用......不是很多额外的,但足够了。

因此,我的应用程序调用System.gc()的唯一时间是它将要进入代码段,其中将分配处理数据所需的大缓冲区,并且对可用空闲内存的测试表明我不是保证拥有它。特别是,我正在寻找一个1GB的环境,其中至少有300mb被静态数据占用,大部分非静态数据是执行相关的,除非正在处理的数据恰好至少为100-200 MB来源。它是自动数据转换过程的一部分,因此从长远来看,数据都存在的时间相对较短。

不幸的是,虽然有关调整垃圾收集器的各种选项的信息可用,但它似乎主要是一个实验过程,并且不容易获得理解如何处理这些特定情况所需的较低级别细节。

所有这一切,即使我使用System.gc(),我仍然继续使用命令行参数进行调整,并设法相对较大的数量改善我的应用程序的整体处理时间,尽管无法克服通过使用更大的数据块构成的绊脚石。话虽这么说,System.gc()是一个工具....一个非常不可靠的工具,如果你不小心你如何使用它,你会希望它不会经常工作。

2
Kyune

通常,VM会在抛出OutOfMemoryException之前自动执行垃圾收集,因此添加显式调用应该没有用,除非它可能会将性能命中移动到更早的时刻。

但是,我认为我遇到了一个可能相关的案例。我不确定,因为我还没有测试它是否有任何影响:

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

1
Vashek

简而言之:

参数是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();
1
mataal

当运行显式GC时,我无法想到一个具体的例子。

通常,运行显式GC实际上可能造成更多弊大于利,因为显式gc将触发完整集合,这会在通过每个对象时花费更长的时间。如果这个显式的gc最终被重复调用,那么很容易导致应用程序变慢,因为花费了大量时间来运行完整的GC。

或者,如果使用堆分析器越过堆并且您怀疑库组件要调用显式GC,则可以将其关闭添加:gc = -XX:+ DisableExplicitGC到JVM参数。

1
zxcv

如果您想知道是否调用了System.gc(),则可以在JVM执行垃圾收集时使用新的Java 7 update 4获取通知。

我不是100%确定 GarbageCollectorMXBean 类是在Java 7更新4中引入的,因为我在发行说明中找不到它,但我在 javaperformancetuning 。com站点中找到了这些信息

1
Shervin Asgari

根据Bruce Eckel的Thinking in Java,一个用于显式 System.gc() call的用例是当你想强制终结时,即调用 finalize 方法。

0
Asterisk

当system.gc工作时,它将停止世界:所有响应都被停止,因此垃圾收集器可以扫描每个对象以检查是否需要删除它。如果应用程序是一个Web项目,所有请求都会停止,直到gc完成,这将导致您的Web项目无法在一个monent中工作。

0
fleture