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


当前回答

jlibs库有一个很好的用于垃圾收集的实用程序类。您可以使用WeakReference对象的一个漂亮的小技巧强制垃圾收集。

RuntimeUtil.gc()从jlibs:

   /**
    * 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();
     }
   }

其他回答

FYI

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

马萨拉特·西迪基

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

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

我想强制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 () ();

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

在带有G1 GC的OracleJDK 10上,对System.gc()的单个调用将导致GC清理旧集合。我不确定GC是否立即运行。但是,即使在循环中多次调用System.gc(), GC也不会清理Young Collection。为了让GC清理Young Collection,你必须在一个循环中分配(例如new byte[1024]),而不调用System.gc()。出于某种原因调用System.gc()会阻止GC清理Young Collection。