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


当前回答

另一种选择是不创建新对象。

对象池是为了减少Java中对GC的需求。

对象池通常不会比对象创建快(特别是对于轻量级对象),但它比垃圾收集快。如果您创建10,000个对象,每个对象是16个字节。GC需要回收160,000个字节。另一方面,如果您不需要同时使用所有10,000个对象,您可以创建一个池来回收/重用对象,这样就不需要构造新对象,也不需要GC旧对象。

类似这样(未经测试)。 如果你想让它是线程安全的,你可以把LinkedList换成ConcurrentLinkedQueue。

public abstract class Pool<T> {
    private int mApproximateSize;
    private LinkedList<T> mPool = new LinkedList<>();

    public Pool(int approximateSize) {
        mApproximateSize = approximateSize;
    }

    public T attain() {
        T item = mPool.poll();
        if (item == null) {
            item = newInstance();
        }
        return item;
    }

    public void release(T item) {
        int approxSize = mPool.size(); // not guaranteed accurate
        if (approxSize < mApproximateSize) {
            recycle(item);
            mPool.add(item);
        } else if (approxSize > mApproximateSize) {
            decommission(mPool.poll());
        }
    }

    public abstract T newInstance();

    public abstract void recycle(T item);

    public void decommission(T item) { }

}

其他回答

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

如果需要强制垃圾收集,也许应该考虑如何管理资源。您正在创建持久化在内存中的大对象吗?您是否正在创建具有Disposable接口的大型对象(例如图形类),并且在使用它时不调用dispose() ?您是否在类级别声明了只需要在单个方法中使用的东西?

如何强制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是一个愚蠢的游戏。

FYI

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

马萨拉特·西迪基

如果您正在使用JUnit和Spring,请尝试在每个测试类中添加以下内容:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)