强制Java虚拟机运行垃圾收集器

时间:2013-02-11 11:59:26

标签: java garbage-collection

我有一个在大型数据集上运行的复杂Java应用程序。该应用程序执行速度相当快,但随着时间的推移,它似乎占用了大量内存并减速。有没有办法在不重新启动应用程序的情况下运行JVM垃圾收集器?

8 个答案:

答案 0 :(得分:16)

,您无法强制垃圾回收 即使使用

System.gc();  

您可以为垃圾收集创建一个请求,但它依赖于JVM来执行此操作。

垃圾收集器也足够聪明,可以在需要时收集未使用的内存,因此您应该检查是否以错误的方式处理对象,而不是强制进行垃圾收集。 如果以错误的方式处理对象(比如保持对不必要的对象的引用),JVM几乎无法释放内存。

来自Doc

  

调用gc方法建议 Java虚拟机消耗   努力回收未使用的物体以制造记忆   它们目前可用于快速重复使用。当控制返回时   从方法调用中, Java虚拟机已尽最大努力   从所有丢弃的物体中回收空间。

关于System.gc()文档

打开Bug
  

System.gc()的文档极具误导性,但未能如实   参考从不调用的推荐做法   System.gc()的

     

语言的选择使得不清楚行为是什么   何时调用System.gc()以及哪些外部因素会影响   行为。

当您认为应该强制JVM释放一些内存时,很少有有用的链接访问 1. How does garbage collection work
2. When does System.gc() do anything
3. Why is it bad practice to call System.gc()?

所有人都说 1.即使System.gc()不保证,你也无法控制Java中的GC 2.强迫它的不良做法也可能对表现产生不利影响 3.重新审视您的设计并让JVM完成他的工作:)

答案 1 :(得分:1)

你不应该继续System.gc() - 如果你觉得你需要强制GC运行它通常意味着你的代码/设计有问题。如果准备好创建,GC将运行并清除未使用的对象 - 请验证您的设计并考虑更多有关内存管理的内容,同时查看对象引用中的循环。

答案 2 :(得分:1)

System.gc() 

在java中调用,建议vm运行垃圾回收。虽然它不能保证它实际上会这样做。然而,你有最好的解决方案。正如其他响应中所提到的,jvisualvm实用程序(自JDK 6更新7以来一直存在于JDK中),也提供了垃圾功能。

编辑:

你的问题打开了我对这个主题的兴趣,我遇到了这个资源:

oracle gc resource

答案 3 :(得分:1)

  

应用程序执行速度相当快,但随着时间的推移,它似乎会消耗大量内存并减慢速度。

这些是Java内存的典型症状。应用程序中的某个位置可能存在一个不断增长的数据结构。随着堆接近满,JVM花费了越来越多的时间来运行GC(无用的)尝试回击一些空间。

强制GC无法解决此问题,因为GC 无法收集数据结构。事实上,强制GC运行只会使应用程序变慢。

问题的解决方法是找出导致内存泄漏的原因,并修复它。

答案 4 :(得分:1)

性能增益/下降取决于您需要垃圾收集的频率以及您的jvm有多少内存以及您的程序需要多少。

当你调用System.gc()时,垃圾收集没有确定性(它只是对解释器的暗示),但至少有可能性。通过足够数量的调用,您可以仅为系统设置实现一些统计派生的性能乘数。

下图显示了示例程序的执行情况'消耗和jvm分别只给出1GB(无gc),1GB(gc),3GB(gc),3GB(无gc)堆。

首先,当jvm只有1GB内存而程序需要3.75GB时,生产者线程池完成工作需要50多秒,因为垃圾管理较少会导致对象创建率不佳。

第二个例子大约快40%,因为在每次生成150MB对象数据之间调用System.gc()。

在第三个例子中,jvm被赋予3GB内存空间,同时保持System.gc()。更多内存提供了更多预期的性能。

但是当我在相同的3GB环境下关闭System.gc()时,速度更快!

即使我们不能强迫它,如果我们尝试足够长的时间,我们可以尝试使用System.g()来获得一些百分比增益或性能消耗。至少在我的Windows-7 64位操作系统上使用最新的jvm。

enter image description here

答案 5 :(得分:0)

垃圾收集器自动运行。你不能强制垃圾收集器。

答案 6 :(得分:0)

我不建议您这样做,但是为了强制垃圾收集器在您的java代码中运行,您可以使用所有可用内存,这是有效的,因为垃圾收集器将在JVM抛出OutOfMemoryError之前运行... < / p>

  try {
        List<Object> tempList = new ArrayList<Object>();
        while (true) {
            tempList.add(new byte[Integer.MAX_VALUE]);
        }
    } catch (OutOfMemoryError OME) {
       // OK, Garbage Collector will have run now...
    }

答案 7 :(得分:0)

我的答案将与其他答案不同,但它会导致同样的观点。 说明: 是的,可以强制垃圾收集器使用两种同时使用的方法,顺序如下:

System.gc();

System.runFinalization();

这两个方法调用将强制垃圾收集器执行任何无法访问的对象的finalize()方法并释放内存。然而,软件的性能将大幅下降,这是因为垃圾在他自己的线程中运行并且无法控制,并且根据垃圾收集器使用的算法可能导致不必要的过度处理,如果你更好检查你的代码,因为它必须被破坏,你需要使用垃圾收集器以良好的方式工作。

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