When does System.gc() do anything
我知道垃圾回收在Java中是自动化的。但我明白,如果在代码中编写EDCOX1(0),Java VM可以在运行时决定是否在该点进行垃圾回收。这是如何精确工作的?当虚拟机看到
实际上,它通常决定进行垃圾收集。答案取决于很多因素,比如运行的是哪个JVM,它处于哪个模式,它使用的是哪个垃圾收集算法。
我不会在你的代码中依赖它。如果jvm将要抛出一个ofmemoryError,那么调用System.gc()不会停止它,因为垃圾收集器将在它达到这个极限之前尝试释放尽可能多的内存。我在实践中唯一一次看到它是在IDES中使用的,它连接到一个用户可以点击的按钮上,但即使在那里,它也没有太大的用处。
我能想到的唯一一个调用System.gc()有意义的例子是在分析应用程序以搜索可能的内存泄漏时。我相信在获取内存快照之前,配置程序会调用这个方法。
您无法控制Java中的GC——VM决定。我从来没有遇到过需要
在某些情况下,向虚拟机建议现在进行完全收集可能是有意义的,因为您可能知道应用程序将在接下来的几分钟内处于空闲状态,然后才进行重载提升。例如,在应用程序启动期间初始化了许多临时对象之后(即,我刚刚缓存了大量信息,我知道在一分钟左右的时间内不会有太多活动)。想想一个IDE,比如Eclipse启动——它需要做很多初始化工作,所以可能在初始化之后立即进行完整的GC是有意义的。
Java语言规范不能保证JVM在调用EDCOX1 OR 0时将启动GC。这就是为什么"可能或可能不决定在那个时候进行GC"。
现在,如果您看看OpenJDK源代码,它是OracleJVM的主干,您会发现对
其他一些答案提到在jconsole或visualvm中启动GC。基本上,这些工具对
通常,您不希望从代码开始垃圾收集循环,因为它会扰乱应用程序的语义。您的应用程序做一些业务工作,JVM负责内存管理。您应该将这些关注点分开(不要让您的应用程序做一些内存管理,而要专注于业务)。
但是,很少有情况下调用
如果你打电话给
我强烈推荐通过Java热点垃圾收集中的文档阅读更多关于垃圾收集的详细信息。
至于何时发布手动收集,您可能希望这样做的唯一时间是放弃包含大量较小收集的大型收集--a比如说,
如果使用直接内存缓冲区,即使直接内存不足,JVM也不会为您运行GC。
如果您调用
大多数JVM将启动GC(取决于-xx:DiableExplicitGC和-xx:+ExplicitgCinvokesConcurrent开关)。但是,为了允许以后更好的实现,规范定义得不太好。
规范需要澄清:bug 6668279:(spec)system.gc()应该表明我们不建议使用,也不保证行为。
在内部,rmi和nio使用gc方法,它们需要同步执行,目前正在讨论:
bug 5025281:允许System.gc()触发并发(而不是停止整个世界)完整集合
我们绝不能强迫垃圾收集。gc只是建议使用vm进行垃圾收集,但是,实际上,机制运行的时间,没有人知道,这是由JSR规范所规定的。
花时间测试各种垃圾收集设置有很多话要说,但是如上所述,这样做通常不有用。
我目前正在研究一个涉及内存有限环境和相对大量数据的项目——有一些大数据块将我的环境推到了极限,即使我能够降低内存使用率,以便理论上它可以正常工作,但我仍然会得到堆空间错误——详细的GC选项。向我展示了它试图收集垃圾,但没有用。在调试器中,我可以执行system.gc(),并确保有足够的"大量"可用内存……不是额外的,而是足够的。
因此,我的应用程序调用System.gc()的唯一时间是它将要进入代码段,在该段中将分配处理数据所需的大缓冲区,并且对可用内存的测试表明我不能保证拥有它。特别是,我正在研究一个1GB环境,其中至少300MB被静态数据占用,其中大部分非静态数据与执行相关,除非正在处理的数据恰好在源位置至少为100-200MB。这都是自动数据转换过程的一部分,所以从长远来看,数据都存在于相对较短的时间内。
不幸的是,虽然可以获得有关调整垃圾收集器的各种选项的信息,但这在很大程度上似乎是一个实验过程,而且不容易获得理解如何处理这些特定情况所需的低级细节。
尽管我使用的是system.gc(),但我仍然继续使用命令行参数进行优化,并设法将应用程序的总体处理时间提高了相当大的一部分,尽管我无法克服处理较大数据块所带来的障碍。也就是说,system.gc()是一个工具……一个非常不可靠的工具,如果你不小心使用它,你会希望它不会经常工作。
EDOCX1·1在EDOCX1·2中是很好的,如果我们正在用Java在桌面/膝上型/服务器上执行软件编码。您可以在
请注意,这些电话都不能保证做任何事情。它们只是建议JVM运行垃圾收集器。无论是否运行GC,都取决于JVM。所以,简短的回答是:我们不知道它何时运行。更长的答案:如果有时间,JVM将运行GC。
我相信,Android也是如此。但是,这可能会减慢系统的运行速度。
当运行显式GC比较好时,我无法想到具体的示例。
一般来说,运行显式GC实际上会造成比好的更多的伤害,因为显式GC将触发一个完整的集合,当它通过每个对象时,会花费更长的时间。如果这个显式GC最终被重复调用,那么很容易导致应用程序速度变慢,因为运行完整GC需要花费大量时间。
或者,如果使用堆分析器遍历堆,并且怀疑库组件正在调用显式GC,则可以将其关闭,将:gc=-xx:+disableexplicitgc添加到jvm参数中。
简而言之:
参数依赖于虚拟机。
示例用法-不能为运行时/生产应用程序考虑一个,但对于某些分析工具(如调用
1 2 3 4 5 6 7 8 | // 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(); |
如果您想知道是否调用了EDCOX1 0调用,则当JVM执行垃圾收集时,可以使用新的Java 7更新4获取通知。
我不是100%肯定的是,在Java 7更新4中引入了GARBACKECOLCORTERMXBE类,因为我在发行说明中找不到它,但是我在JavaPrimeCutuunnCo站点找到了信息。
通常,在抛出OutOfMemoryException之前,VM会自动执行垃圾收集,因此添加显式调用不应该有帮助,除非它可能会将性能影响移动到更早的时间。
但是,我认为我遇到了一个可能与之相关的案例。但我不确定,因为我还没有测试它是否有任何效果:
当内存映射文件时,我相信map()调用会在没有足够大的内存块时抛出IOException。我认为,在map()文件之前进行垃圾收集可能有助于防止这种情况发生。你怎么认为?
根据Bruce Eckel的Java思想,显式系统.gc-()调用的一个用例是强制终结,即调用终结方法。
当system.gc工作时,它将停止整个世界:所有响应都将停止,垃圾收集器可以扫描每个对象以检查是否需要删除它。如果应用程序是Web项目,所有请求都将停止,直到GC完成,这将导致您的Web项目无法在monent中工作。