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


当前回答

在未来的版本中,.gc可能会被淘汰——一位Sun工程师曾经评论说,世界上可能只有不到20人真正知道如何使用.gc()——我昨晚花了几个小时研究一个中心/关键数据结构,使用securerrandom生成的数据,当超过40000个对象时,虚拟机就会变慢,就像指针用光了一样。显然,它被16位指针表所阻塞,并表现出典型的“机械故障”行为。

我尝试了-Xms等等,一直在旋转,直到它运行到大约57,xxx什么的。然后,在gc()之后,它将运行gc,从57,127到57,128——大约是Easy Money营地代码膨胀的速度。

你的设计需要基本的重新工作,可能是一个滑动窗口的方法。

其他回答

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

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

在未来的版本中,.gc可能会被淘汰——一位Sun工程师曾经评论说,世界上可能只有不到20人真正知道如何使用.gc()——我昨晚花了几个小时研究一个中心/关键数据结构,使用securerrandom生成的数据,当超过40000个对象时,虚拟机就会变慢,就像指针用光了一样。显然,它被16位指针表所阻塞,并表现出典型的“机械故障”行为。

我尝试了-Xms等等,一直在旋转,直到它运行到大约57,xxx什么的。然后,在gc()之后,它将运行gc,从57,127到57,128——大约是Easy Money营地代码膨胀的速度。

你的设计需要基本的重新工作,可能是一个滑动窗口的方法。

我们可以使用java运行时触发jmap -histo:live <pid>。这将强制在堆上进行完整的GC,以标记所有活动对象。

public static void triggerFullGC() throws IOException, InterruptedException {
    String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
    Process process = Runtime.getRuntime().exec(
            String.format("jmap -histo:live %s", pid)
    );
    System.out.println("Process completed with exit code :" + process.waitFor());
}

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

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

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的可移植方式。