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


当前回答

如果您正在运行内存并得到一个OutOfMemoryException,您可以尝试通过java -Xms128m -Xmx512m开始编程来增加java可用的堆空间的数量,而不仅仅是java。这将使您的初始堆大小为128Mb,最大堆大小为512Mb,远远超过标准的32Mb/128Mb。

其他回答

如果您正在运行内存并得到一个OutOfMemoryException,您可以尝试通过java -Xms128m -Xmx512m开始编程来增加java可用的堆空间的数量,而不仅仅是java。这将使您的初始堆大小为128Mb,最大堆大小为512Mb,远远超过标准的32Mb/128Mb。

最好的选择是调用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的可移植方式。

如何强制Java GC

好了,这里有几种强制Java GC的不同方法。

单击JConsole的Perform GC按钮 使用JMap的JMap -histo:live 7544命令,其中7544是pid 调用Java诊断控制台的jcmd 7544 GC.run命令 调用system . gc ();在代码中 .gc调用Runtime.getRuntime () ();在代码中

这些都不行

这是一个肮脏的小秘密。这些方法都不能保证有效。你真的不能强制Java GC。

Java垃圾收集算法是不确定的,虽然所有这些方法都可以激励JVM执行GC,但实际上不能强制执行。如果JVM有太多事情要做,而停止世界操作是不可能的,那么这些命令要么会出错,要么会运行,但GC实际上不会发生。

if (input.equalsIgnoreCase("gc")) {
    System.gc();
    result = "Just some GC.";
}

if (input.equalsIgnoreCase("runtime")) {
    Runtime.getRuntime().gc();
    result = "Just some more GC.";
}

解决恼人的问题

如果遇到内存泄漏或对象分配问题,请修复它。坐在那里,手指放在Java任务控制的强制Java GC按钮上,只会拖延时间。使用Java Flight Recorder配置应用程序,在VisualVM或JMC中查看结果,并修复问题。试图强制Java 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();
     }
   }