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


当前回答

FYI

方法调用System.runFinalizersOnExit(true)保证终结器方法 在Java关闭之前调用。然而,这种方法本质上是不安全的 并且已经被弃用。另一种方法是在方法中添加“关机钩子” Runtime.addShutdownHook。

马萨拉特·西迪基

其他回答

我想强制gc,因为当它发生时,我的代码被冻结了很长时间。其目的是通过定期引起gc来平滑充电。 所列出的解决方案在我的环境中并不强制。

So:

我请求内存临时变量, 简单地,通过增量, 并监视内存并在触发gc时立即停止操作。

它很容易工作,但你必须调整。

Runtime rt = Runtime. getruntime (); double usedMB = (rt.totalMemory() - rt.freeMemory()) / 1024 / 1024; if (usedMB > 1000) //只在必要时使用 { Byte [][] for_nothing = new Byte [10][]; For (int k = 0;K < 10;k + +) For_nothing [k] = new byte[100_000_000]; } system . gc (); .gc Runtime.getRuntime () (); .runFinalization Runtime.getRuntime () ();

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

jdk1.7.0/bin/jcmd <pid> GC.run

看到的:

https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html

有一些间接的方法来强制垃圾收集器。您只需要用临时对象填充堆,直到垃圾收集器执行为止。我已经创建了一个类,它以这样的方式强制垃圾收集器:

class GarbageCollectorManager {

    private static boolean collectionWasForced;
    private static int refCounter = 0;

    public GarbageCollectorManager() {
        refCounter++;
    }

    @Override
    protected void finalize() {
        try {
            collectionWasForced = true;
            refCounter--;
            super.finalize();   
        } catch (Throwable ex) {
            Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public int forceGarbageCollection() {
        final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;
        int iterationsUntilCollected = 0;
        collectionWasForced = false;

        if (refCounter < 2) 
            new GarbageCollectorManager();

        while (!collectionWasForced) {
            iterationsUntilCollected++;
            int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC];
            arr = null;
        }

        return iterationsUntilCollected;
    }

}

用法:

GarbageCollectorManager manager = new GarbageCollectorManager();
int iterationsUntilGcExecuted = manager.forceGarbageCollection();

我不知道这个方法有多有用,因为它不断地填充堆,但如果你有任务关键的应用程序必须强制GC -当这可能是Java强制GC的可移植方式。

FYI

方法调用System.runFinalizersOnExit(true)保证终结器方法 在Java关闭之前调用。然而,这种方法本质上是不安全的 并且已经被弃用。另一种方法是在方法中添加“关机钩子” Runtime.addShutdownHook。

马萨拉特·西迪基

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

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

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

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

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