迭代中创建Java垃圾收集对象

时间:2012-09-26 19:37:56

标签: java garbage-collection

看看以下代码

for(int i = 0; i < 10; i++) {
    new Object();
}

垃圾收集器是否会在每次迭代中启动,因为没有对象的引用?通常不鼓励在没有任何引用的情况下在迭代中创建对象吗?

7 个答案:

答案 0 :(得分:3)

  

垃圾收集器是否会在每次迭代中启动,因为没有对该对象的引用?

可能不是。这并不像JVM通常被引用计算一样。将创建少量垃圾 - 每个对象在迭代后将符合条件进行收集,但是当这些对象实际上收集时未指定。

  

通常不鼓励在没有任何引用的情况下在迭代中创建对象吗?

创建任何目的的对象通常不是一个好主意。我不确定你的意思是“没有任何参考”。如果你有一个原因在每次迭代中创建一个新对象,并且在迭代完成后就没有必要,那就没问题了。

答案 1 :(得分:2)

Java无法保证垃圾收集何时启动。它只对GC提出一个保证(我在这里解释):

  

最终,引用计数为0的超出范围的对象将是垃圾   收集。

即使致电System.gc()也无法保证任何事情。远离任何依赖于非确定性行为的代码。

正如Jon Skeet指出的那样,大多数Java GC都不使用引用计数。在这里阅读更多http://www.ibm.com/developerworks/java/library/i-garbage2/http://www.ibm.com/developerworks/java/library/i-garbage1/(文章是关于IBM的VM - 其他VM的GC算法可能不同)。我主要使用术语作为过度简化。

答案 2 :(得分:1)

不,垃圾收集器不会在每次迭代时启动。收集器并不完全确定 - 没有一组特定的约束导致它运行。垃圾收集器不会仅仅因为您创建了可以收集的对象而运行。

但是,在每次迭代中创建的Object立即有资格进行垃圾收集 - 这是两个不同的概念。

答案 3 :(得分:1)

您不知道GC何时运行。

在循环堆上创建的每个对象在超出范围时都符合GC的条件,但不保证每次迭代都运行GC。

答案 4 :(得分:1)

当生成已满(或在某个占用时),垃圾收集器启动,而不是在代码块退出时启动。

答案 5 :(得分:1)

针对短期对象优化的垃圾收集的注释是有效的。

此外,请注意,HotSpot 的方面在这种情况下也会影响垃圾收集。

Escape Analysis已添加到Java 6中的Oracle / OpenJDK JVM中,并且是enabled by default in the HotSpot compiler of OpenJDK 7

  

转义分析是Java Hotspot Server的一种技术   编译器可以分析新对象的使用范围并做出决定   是否在Java堆上分配它。

理论上,这将允许编译器确定该对象只能在方法中访问,因此可以在堆栈而不是堆上分配。因此,可以在每次迭代结束时从内存中释放,而根本不需要垃圾收集(类似于在每次迭代后显式释放C / C ++中的内存)。

实际上,documentation for escape analysis in OpenJDK 7表示JDK 7编译器当前“不会用非全局转义对象的堆栈分配替换堆分配”。因此,堆栈分配似乎是可以实现的优化(IMO),但现在似乎没有实现。

另一个优化是编译器(或HotSpot)检测到此示例中创建的对象从未使用过,并且其构造函数不会修改应用程序中其他位置的状态/原因副作用。在这种情况下,它可以完全消除编译代码中的语句,因此永远不会执行new Object()

总之,HotSpot继续变得更加智能,并且对此类案例进行了一些优化。

现在(正如其他人所提到的)GC不太可能在每次迭代后立即启动,但它很可能很快就会释放这些物体(伊甸园空间/年轻一代等)。

将来HotSpot可能会使用堆栈分配,因此在每次迭代后确实释放内存。或者编译器或HotSpot可能完全消除这个特定的语句。

答案 6 :(得分:0)

  

垃圾收集器是否会在每次迭代中启动

你不知道也不应该关心这些对象将在年轻一代中,并且该区域的清理速度很快(需要小房子保养)。

  

通常不鼓励在没有任何迭代的情况下创建对象   参考?

取决于。如果是这样的话,即在本地范围中创建匿名对象实际上可以帮助GC将其识别为符合GC的条件。