如何在Java中强制进行垃圾收集?

208 java garbage-collection

是否有可能在Java中强制进行垃圾收集,即使它很棘手?我知道System.gc();,Runtime.gc();但他们只建议做GC.我怎么强迫GC?

And*_*are 159

您最好的选择是调用System.gc()哪个只是垃圾收集器的提示,您希望它进行收集.由于垃圾收集器是非确定性的,因此无法强制立即收集.

  • 应该有.`non-deterministic == trouble` (23认同)
  • 垃圾收集器可能是非确定性的,并且仍然提供强制立即收集的方法.例如,通常.NET收集器是非确定性的,但是对GC.Collect()的调用会强制它运行.这只是Java选择不公开这个功能. (7认同)
  • @Pacerier 如果您想要确定性行为,现在可以使用 Epsilon 垃圾收集器。它绝对不会收集任何东西。 (4认同)
  • 根据我的经验,这个方法总是调用垃圾收集器.它具有足够的规律性,使得我的内存使用量与声明的对象数量总是严格线性的(考虑填充等). (2认同)

sha*_*ams 53

jlibs库中有垃圾收集一个很好的实用工具类.你可以使用WeakReference对象的一个漂亮的小技巧强制垃圾收集.

来自jlibs的RuntimeUtil.gc():

   /**
    * This method guarantees that garbage collection is
    * done unlike <code>{@link System#gc()}</code>
    */
   public static void gc() {
     Object obj = new Object();
     WeakReference ref = new WeakReference<Object>(obj);
     obj = null;
     while(ref.get() != null) {
       System.gc();
     }
   }
Run Code Online (Sandbox Code Playgroud)

  • OP要求,并声称提供"强制垃圾收集"的解决方案.运行GC子系统是一回事,实际上是另外收集垃圾.您提供的代码示例显然有意保证已收集垃圾.无论如何,这是一个非常古老的问题,显然不是关于OP的愿望,而是对公众的实用性.没有人对"强制GC子系统自行运行"感兴趣,没有收集垃圾.事实上,人们通常希望保证**已经收集了所有垃圾**. (19认同)
  • 您可能没有将它与`System.gc()的效率进行比较; System.gc();`,但知道它是否曾经比那更好用,这肯定会很有趣.事实上,只需打印多少次它称为`System.gc()`就足够了.达到2的机会相当渺茫. (4认同)
  • 所以基本上,这段代码没有什么比 `System.gc()` 更好的了。被清除的 `WeakReference` 与内存回收无关。我个人测试了该代码,发现它没有用。可笑的简单代码`System.gc(); System.gc();` 有更好的结果。 (2认同)
  • @MarkoTopolnik:“没有人对自己“强制GC子系统运行”感兴趣,没有收集到垃圾”。...实际上,我今天对这种行为很感兴趣。我很感谢这个答案的存在。我的目的是检查GC日志处理的旋转行为,并获取GC输出的格式。这个小技巧可帮助我快速填写GC日志。 (2认同)

Mai*_*guy 45

强制GC的最佳方法(如果不是唯一的方法)是编写自定义JVM.我相信垃圾收集器是可插拔的,所以你可以选择一个可用的实现并调整它.

注意:这不是一个简单的答案.

  • +1为lulz.没有什么能比那些有幽默感的人更令人沮丧的调试.除了一个实际可用的答案,那就是. (36认同)

tra*_*god 40

使用Java™虚拟机工具接口(JVM TI),该功能

jvmtiError ForceGarbageCollection(jvmtiEnv* env)
Run Code Online (Sandbox Code Playgroud)

将"强制VM执行垃圾收集".JVM TI是JavaTM平台调试器架构(JPDA)的一部分.

  • 此API在许多[profilers]中使用(http://stackoverflow.com/q/2064427/230513). (7认同)

leg*_*ira 24

是的,几乎可以强制你必须以相同的顺序调用方法,同时这些方法是:

System.gc ();
System.runFinalization ();
Run Code Online (Sandbox Code Playgroud)

即使只是一个对象来清理这两个方法的使用同时强制垃圾收集器使用finalise()不可达对象的方法释放分配的内存并执行finalize()方法所述的操作.

然而,使用垃圾收集器是一种可怕的做法,因为使用垃圾收集器可能会给软件带来过载甚至可能比内存更糟糕,垃圾收集器有自己的线程,这是不可能控制加上取决于gc使用的算法可能需要更多的时间并且考虑效率非常低,你应该在gc的帮助下检查你的软件是否最糟糕,因为它肯定是坏的,一个好的解决方案不能依赖于gc.

注意:只是要记住这只有在finalize方法不是对象的重新分配时才有效,如果发生这种情况,对象将保持活着,它将具有技术上可能的复活.

  • *NO*,即使这两个命令也不会强制进行垃圾回收.正如其他人已经提到的,`gc()`只是一个运行垃圾收集的提示.`runFinalizers()`只在"被发现被丢弃"的对象上运行终结器.如果gc实际上没有运行,可能没有这样的对象...... (10认同)

Pet*_*ham 20

OutOfMemoryError的文档中,它声明除非VM在完全垃圾回收后无法回收内存,否则不会抛出它.因此,如果您继续分配内存直到出现错误,那么您将已经强制进行完整的垃圾回收.

据推测,你真正想问的问题是"我怎么能回收我认为我应该通过垃圾收集来回收的内存?"


Pin*_*rma 16

要手动请求GC(而不是从System.gc()):

  1. 转至:JDK中的bin文件夹eg.-C:\ Program Files\Java\jdk1.6.0_31\bin
  2. 打开jconsole.exe
  3. 连接到所需的本地进程.
  4. 转至内存选项卡,然后单击执行GC.

  • Oppsss误导.请将鼠标悬停在"执行GC"按钮上.您可以请求JVM执行GC但不要强制执行. (3认同)

Nic*_*dan 11

.gc是未来版本中的淘汰候选者 - 一位太阳工程师曾评论说,世界上可能只有不到二十人真正知道如何使用.gc() - 我昨晚在中心/关键时刻做了几个小时的工作数据结构使用SecureRandom生成的数据,在某个地方只有超过40,000个对象,vm会慢下来,好像它已经用尽指针一样.显然,它正在扼杀16位指针表并展示经典的"失败的机械"行为.

我尝试了-Xms等等,一直都在努力,直到它运行到大约57,xxx的东西.然后它会在gc()之后运行从57,127到57,128的gc - 大约在Easy Money营地的代码膨胀速度.

您的设计需要基本的重新工作,可能是滑动窗口方法.

  • 废话!有一个明显的例子应该使用它:测试使用弱引用的代码,以便我们可以确保在弱引用被清除时行为是正确的. (5认同)

小智 11

您可以从命令行触发GC.这对batch/crontab非常有用:

jdk1.7.0/bin/jcmd <pid> GC.run
Run Code Online (Sandbox Code Playgroud)

见:


rai*_*mar 6

JVM规范没有说明垃圾收集的具体内容.因此,供应商可以自由地实施GC.

因此,这种模糊性导致垃圾收集行为的不确定性.您应该检查您的JVM详细信息,以了解垃圾收集方法/算法.此外,还有自定义行为的选项.


Cam*_*zie 6

如何强制 Java GC

好的,这里有几种不同的方法来强制Java GC。

  1. 单击 JConsole 的Perform GC按钮
  2. 使用 JMap 的jmap -histo:live 7544命令,其中 7544 是 pid
  3. 调用 Java 诊断控制台的jcmd 7544 GC.run命令
  4. 调用System.gc();你的代码
  5. 打电话Runtime.getRuntime().gc(); 在你的代码中

在此处输入图片说明

这些都不起作用

这是肮脏的小秘密。这些都不能保证工作。你真的不能强制 Java GC

Java 垃圾收集算法是非确定性的,虽然所有这些方法都可以激励 JVM 进行 GC,但您实际上不能强制它。如果 JVM 有太多事情发生并且无法执行 stop-the-world 操作,这些命令要么出错,要么运行但实际上不会发生 GC。

if (input.equalsIgnoreCase("gc")) {
    System.gc();
    result = "Just some GC.";
}

if (input.equalsIgnoreCase("runtime")) {
    Runtime.getRuntime().gc();
    result = "Just some more GC.";
}
Run Code Online (Sandbox Code Playgroud)

解决该死的问题

如果您遇到内存泄漏或对象分配问题,请修复它。用你的手指坐在 Java Mission Control 的Force Java GC按钮上只会让事情变得更糟。使用Java Flight Recorder 分析您的应用程序,在 VisualVM 或 JMC 中查看结果,并修复问题。试图强制 Java GC是一个傻瓜游戏。

在此处输入图片说明