Java垃圾收集

时间:2011-02-23 03:48:38

标签: java garbage-collection

Java自动调用垃圾收集器,那为什么我们需要手动调用垃圾收集?何时应使用 System.gc()

7 个答案:

答案 0 :(得分:43)

  

Java自动调用垃圾收集器,那为什么我们需要手动调用垃圾收集?

我们不需要它们。实际上,在大多数情况下,调用System.gc() 对应用程序性能有害。有关详细说明,请参阅我对"Why is it a bad practice to call system gc"的回答。

  

什么时候应该使用System.gc()

如果应用程序知道它进入了一个没有其他任何操作的阶段并且用户不太可能注意到垃圾收集,那么也许可以调用System.gc()以阻止用户在将来遇到GC停顿。

缺点包括:

  • 调用System.gc()通常会触发一个完整的GC,这比“新空间”的GC要长得多。
  • 用户可能实际关心/注意。例如,如果您在游戏中的“级别”之间调用System.gc(),则需要更长时间加载下一级别。
  • 通过强制GC,您导致JVM使用额外的CPU周期等,这可能会干扰用户在其计算机上执行的其他事情。

(在单元测试和系统调试期间调用System.gc()也有合理的理由。)

答案 1 :(得分:14)

无需显式调用垃圾收集,并且调用System.gc()只是建议,JVM可以忽略您的建议。

我能想到的唯一实际用途是

  1. 在调试期间,强制收集可能会暴露内存泄漏
  2. 如果程序经历了可预测的强烈计算周期而没有计算(如基于回合的游戏),则在无计算周期期间,CPU可以用于建议的垃圾收集以防止在强烈计算部分期间的抖动。

答案 2 :(得分:4)

System.gc()只是一个建议。但在某些情况下它确实有意义。

假设您有MyClass类,并且您想知道一个实例占用多少内存。你能做的就是这个(粗略地说):

MyClass [] objects= new MyClass[100000];
System.gc();
long memoryNow = Runtime.getRuntime().freeMemory();
for (int i = 0; i < 100000; i ++) {
  objects[i] = new MyClass();
}
System.gc();
long memoryLater = Runtime.getRuntime().freeMemory();
int objectSize = (int)((memoryLater - memoryNow) / 100000);

还有其他类似的案例,我发现System.gc()很有用。

答案 3 :(得分:1)

当没有足够的内存将新对象分配到堆中时,JVM始终会调用垃圾收集器。在调用垃圾收集器时,它遵循Stop the World规范,为此它调用System.gc()方法。

还要记住,JVM还运行并行gc线程以从内存中删除未使用的对象。因此,所有内容和每一分钟JVM都会维护堆内存并始终尝试不会使其超载。因此,无需明确调用System.gc()Runtime.gc()方法。

如果您想了解更多详细信息,可以获取相关信息here

答案 4 :(得分:1)

尚未提及的一个方面是某些类型的对象可能要求外部的实体代表他们做事(例如,让他们独立访问不可替换的资源,如文件),这会损害其他实体。执行垃圾收集时,系统不仅会释放以前由无法访问的对象占用的内存,而且还会在其通知已被放弃的对象上调用finalize,从而允许此类对象通知外部不再需要其服务的实体。程序完全有可能达到内存充足的状态,但必要的资源不可用,因为对象已被授予独占访问权限,并且在不释放对象的情况下被放弃。强制垃圾收集器在这种情况下运行有时可以释放必要的资源。

答案 5 :(得分:0)

垃圾收集过程不受用户控制。所以明确调用System.gc();是没有意义的。 完全取决于JVM。

几天前,我问过完全相同的问题:[Here]

事实上,许多与明确调用System.gc();相关的问题已经在这里得到了回答。明确地调用System.gc();始终被视为 编程技能,尽管它不会造成任何伤害。

以下是我应该通过的几个链接。它肯定会澄清你的疑问。

  PS:顺便说一下,你应该认真对待    额外 努力完成的工作   类似的StackOverflow问题在发布您的疑问之前。

答案 6 :(得分:0)

无需致电System.gc()Runtime.getRuntime().gc()。如果JVM发现内存不足,则内部控制垃圾收集。