我知道 JVM GC 喜欢短期对象的原因,因为它可以在次要 GC 中收集。但是为什么 JVM GC 喜欢不可变对象呢?
编辑:查理亨特在他的演讲中说 GC 喜欢不可变对象。
谢谢
如果 GC 可以知道一个对象不包含对任何 gen0 对象的任何引用,那么在执行 gen0 收集时可以忽略它。同样,如果一个对象不包含对任何 gen0 或 gen1 对象的任何引用,则在执行 gen1 收集时可能会忽略它。在收集过程中可以忽略的对象越多,收集的速度就越快。
如果一个对象在 gen0 GC 中幸存下来,则可以确定它持有引用的任何 gen0 对象都将被提升为 gen1;同样,如果一个不包含任何 gen0 引用的对象在 gen1 GC 中幸存下来,则它包含的任何 gen1 引用都将被提升为 gen2。因此,一旦在 gen0 收集期间检查了一个对象,除非它被修改,否则在下一次 gen1 收集之前不需要再次检查它。同样,在 gen1 收集期间检查的对象在下一次 gen2 收集之前不需要检查,除非它被修改。
知道对象是否被修改是一个棘手的问题,但关键是如果对象没有被修改,这对 GC 非常有利。
感谢您的链接..觉得很好:)
来自介绍:GC 喜欢小的不可变对象和短暂的对象。
编辑:
较小的对象具有较短的内存占用,这意味着在收集后不会有太多的内存压缩开销(内存压缩对于大对象来说很慢,因为它们在被 GC 回收后会留下更大的内存空洞)。短期对象也很好,因为它们在次要 GC 周期中被收集。
我从 Brian Goetz 的文章中找到了答案。
在大多数情况下,当持有者对象被更新以引用不同的对象时,新的所指对象是一个年轻的对象。如果我们通过调用 setValue() 来更新一个 MutableHolder,我们就创造了一个旧对象引用一个新对象的情况。另一方面,通过创建一个新的 ImmutableHolder 对象,一个较年轻的对象正在引用一个较旧的对象。后一种情况,大多数对象指向较旧的对象,对分代垃圾收集器来说要温和得多。如果旧代中的 MutableHolder 发生了变异,则必须在下一次次要集合中扫描卡上包含 MutableHolder 的所有对象以查找从旧到新的引用。对长期存在的容器对象使用可变引用增加了在收集时跟踪从旧到新的引用所做的工作。