是否有可能在Java中强制垃圾收集,即使这很棘手?我知道System.gc();和Runtime.gc ();但他们只建议做GC。如何强制GC?


当前回答

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

转到:bin文件夹在JDK中,例如。c: \ Program Files \ Java \ jdk1.6.0_31 \ bin 打开jconsole.exe 连接到所需的本地进程。 进入“内存”页签,单击“执行GC”。

其他回答

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

System.gc ();
System.runFinalization ();

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

不过是一个可怕的实践使用垃圾收集器,因为使用它可能会引入一个加载的软件可能甚至比在内存坏,垃圾收集器有自己的线程是不可能控制+根据gc可能需要更多的时间和所使用的算法是考虑非常低效,您应该检查您的软件如果它坏在gc的帮助,因为它绝对是坏,一个好的解决方案不能依赖于gc。

注意:只是要记住,只有在finalize方法中没有对对象进行重赋时,这才会起作用,如果发生这种情况,对象将保持存活,它将有一个复活,这在技术上是可能的。

最好的选择是调用System.gc(),这只是给垃圾收集器一个提示,表明您希望它进行收集。由于垃圾收集器是不确定的,因此没有办法强制和立即回收。

I did some experimentation (see https://github.com/mikenakis/ForcingTheJvmToGarbageCollect) trying about a dozen different ways of performing a garbage collection, including ways described in this answer, and more, and I found that there is absolutely no frigging way to deterministically force the JVM to do a complete garbage collection. Even the best answers to this question are only partially successful in that the best they achieve is some garbage collection, but never a guaranteed full garbage collection.

我的实验表明,下面的代码片段产生了最好的(最不坏的)结果:

public static void ForceGarbageCollection()
{
    long freeMemory = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();
    for( ; ; )
    {
        Runtime.getRuntime().gc();
        Runtime.getRuntime().runFinalization();
        long newFreeMemory = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();
        if( newFreeMemory == freeMemory )
            break;
        freeMemory = newFreeMemory;
        sleep( 10 );
    }
}

其中sleep()函数如下:

private static void sleep( int milliseconds )
{
    try
    {
        Thread.sleep( milliseconds );
    }
    catch( InterruptedException e )
    {
        throw new RuntimeException( e );
    }
}

不幸的是,睡眠中的数字10是有魔力的;它假设您每秒执行中等数量的内存分配,这将导致中等数量的结束。如果你通过对象的速度更快,那么10可能是不够的,你可能需要等待更长的时间。您可以将其设置为100,但无论您将其设置为多少,总有可能它不够用。

话虽如此,在一个受控制的环境中,10个就足够了,这种方法被观察到可以持续地从内存中消除所有不可访问的对象,而本问答中提到的其他方法都不能做到这一点。我在github上链接的实验代码证明了这一点。

在我看来,Java虚拟机没有提供执行强制的、无条件的、确定的、绝对彻底的、让世界停止的垃圾收集的方法,这一事实使它崩溃了。

换句话说,JVM的创造者是如此傲慢,以至于认为他们比我们更了解我们是否想要这样做,或者我们是否应该这样做。别那么傲慢。如果某些东西像魔法一样起作用,那么必须提供一些绕过魔法的方法。

我想在这里补充一些东西。请不要说Java运行在虚拟机而不是实际的机器上。虚拟机有自己的与机器通信的方式。它可能因系统而异。现在,当我们调用GC时,我们要求Java虚拟机调用垃圾收集器。

由于垃圾收集器是与虚拟机一起使用的,我们不能强迫它当场进行清理。相反,我们将请求与垃圾收集器一起排队。这取决于虚拟机,在特定时间之后(这可能因系统而异,通常在分配给JVM的阈值内存已满时),实际机器将释放空间。: D

在OutOfMemoryError的文档中,它声明除非虚拟机在完整的垃圾回收后未能回收内存,否则它不会被抛出。因此,如果您一直分配内存直到出现错误,那么您将已经强制进行完整的垃圾收集。

想必您真正想问的问题是“如何回收我认为应该通过垃圾收集回收的内存?”