在Java中是否可以强制进行垃圾回收?即使有些棘手,我知道System.gc();
和Runtime.gc();
但它们只是建议进行GC。那么如何强制GC呢?
在Java中是否可以强制进行垃圾回收?即使有些棘手,我知道System.gc();
和Runtime.gc();
但它们只是建议进行GC。那么如何强制GC呢?
System.gc()
方法,它只是向垃圾回收器发出一个提示要进行垃圾回收。虽然垃圾收集器是非确定性的,但没有办法强制立即进行垃圾回收。jlibs库提供了一个很好的垃圾收集实用程序类。你可以使用WeakReference对象的一个巧妙小技巧来强制进行垃圾收集。
在jlibs中,可以使用RuntimeUtil.gc()方法进行垃圾收集:
/**
* 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();
}
}
System.gc()
没有什么不同。WeakReference
对象被清除与内存回收无关。我亲自测试过该代码并发现其毫无作用。而极其简单的代码 System.gc(); System.gc();
的效果要好得多。 - Marko TopolnikSystem.gc(); System.gc();
的效率进行比较,但是知道它是否比后者更有效会很有趣。事实上,仅打印调用 System.gc()
次数的信息就足够了。达到 2 的机会非常渺茫。 - Marko TopolnikSystem.gc()
命令,也无法可靠地发送......(想一想 - 当它到达循环时,没有保证WeakReference仍然指向任何东西。) - Steffen Heil如果要强制进行垃圾回收,最好(如果不是唯一的方法)就是编写一个定制的JVM。我认为垃圾收集器是可插拔的,因此您可能只需选择其中一种可用的实现并进行调整。
注意:这不是一个简单的答案。
通过使用Java™虚拟机工具接口(JVM TI),这个函数可以实现
jvmtiError ForceGarbageCollection(jvmtiEnv* env)
将“强制VM执行垃圾回收”。JVM TI是Java平台调试体系结构(JPDA)的一部分。
是的,强制按照相同顺序和时间调用这两个方法几乎是可能的,它们分别是:
System.gc ();
System.runFinalization ();
即使只有一个要清理的对象,同时使用这两种方法也会强制垃圾收集器使用finalise()
方法来释放已分配的内存并执行finalize()
方法规定的操作。
然而,使用垃圾收集器是一种可怕的做法,因为它可能会对软件产生比内存更糟糕的负荷,垃圾收集器有自己的线程,无法控制,而且取决于gc使用的算法,可能需要更长的时间,并且被认为非常低效,如果使用gc导致软件变得更糟,那么您应该检查您的软件,因为它肯定存在问题。一个好的解决方案不应该依赖于gc。
注意: 请记住,仅当在最终方法中没有重新分配对象时,此方法才有效,如果发生这种情况,则对象将保持活动状态并可能出现技术上可能的“复活”。
gc()
只是一个提示来运行垃圾回收。runFinalizers()
只会对“已被发现已经被丢弃”的对象运行终结器。如果垃圾回收没有实际运行,则可能没有这样的对象存在... - Steffen Heiljdk1.7.0/bin/jcmd <pid> GC.run
请参见:
手动请求GC(非System.gc())的方法:
以下是几种不同的方法来 强制 Java 垃圾回收。
Perform GC
按钮jmap -histo:live 7544
命令,其中7544是pidjcmd 7544 GC.run
命令System.gc();
Runtime.getRuntime().gc()
;这里有个小秘密。这些方法都不能保证起作用。你真的不能强制Java垃圾回收。
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 Mission Control的 Force Java GC
按钮上闲逛只会推迟问题。使用Java Flight Recorder对应用程序进行剖析,使用VisualVM或JMC查看结果,并解决问题。试图强制Java GC是一场愚人游戏。
在未来的版本中,.gc 可能会被淘汰 - 一位 Sun 工程师曾经评论说,世界上可能只有不到二十个人真正知道如何使用 .gc() - 昨晚我做了一些工作,花费了几个小时在一个关键的数据结构上,使用 SecureRandom 生成的数据,在大约 40,000 个对象之后,虚拟机会变慢,好像它已经用完了指针。显然,它被卡在了 16 位指针表上,并展现了经典的 "故障机器" 行为。
我尝试使用 -Xms 等参数,一直进行位操作,直到它可以运行到大约 57,xxx。然后它会在 gc() 后从 57,127 跳到 57,128 - 在像 Easy Money 训练营那样的代码膨胀速度下运行。
你的设计需要进行基本的重新设计,可能需要采用滑动窗口方法。