看看以下代码
for(int i = 0; i < 10; i++) {
new Object();
}
垃圾收集器是否会在每次迭代中启动,因为没有对象的引用?通常不鼓励在没有任何引用的情况下在迭代中创建对象吗?
答案 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的条件。