Object 为什么JVM';s GC?

Object 为什么JVM';s GC?,object,garbage-collection,jvm,immutability,Object,Garbage Collection,Jvm,Immutability,我知道JVM GC喜欢短命对象的原因,因为它可以在次要GC中收集。但是为什么JVM GC喜欢不可变的对象呢 编辑: Charlie Hunt说GC喜欢他作品中的不可变对象 谢谢谢谢你的链接..觉得很好:) 来自演示文稿:GC喜欢小的不可变对象和短期对象 编辑: 较小的对象具有较短的内存占用,这意味着在收集之后,内存压缩不会有太大的开销(对于较大的对象,内存压缩比较慢,因为它们在被GC回收后会留下较大的内存漏洞)。短寿命的对象也很好,因为它们是在较小的GC循环中收集的 我从布赖恩·戈茨的书中找到了

我知道JVM GC喜欢短命对象的原因,因为它可以在次要GC中收集。但是为什么JVM GC喜欢不可变的对象呢

编辑: Charlie Hunt说GC喜欢他作品中的不可变对象


谢谢

谢谢你的链接..觉得很好:)

来自演示文稿:GC喜欢小的不可变对象和短期对象

编辑:


较小的对象具有较短的内存占用,这意味着在收集之后,内存压缩不会有太大的开销(对于较大的对象,内存压缩比较慢,因为它们在被GC回收后会留下较大的内存漏洞)。短寿命的对象也很好,因为它们是在较小的GC循环中收集的

我从布赖恩·戈茨的书中找到了答案

在大多数情况下,当holder对象更新为引用不同的对象时,新的referent是一个年轻的对象。如果我们通过调用setValue()来更新一个MutableHolder,那么我们就创建了一个旧对象引用新对象的情况。另一方面,通过创建新的ImmutableHolder对象,较年轻的对象将引用较旧的对象。后一种情况是,大多数对象指向较旧的对象,这对于分代垃圾收集器来说要温和得多。如果生活在旧一代的易变持有人发生变异,则必须在下一次小收集时扫描卡上包含易变持有人的所有对象,以查找从旧到新的引用。对长寿命容器对象使用可变引用增加了在收集时跟踪从旧引用到新引用的工作量


如果GC可以知道某个对象不包含对任何gen0对象的任何引用,那么在执行gen0集合时可以忽略该对象。同样,如果对象不包含对任何gen0或gen1对象的任何引用,则在执行gen1集合时可能会忽略该对象。在收集过程中可以忽略的对象越多,收集的速度就越快

如果一个对象在gen0 GC中幸存下来,它可以确保它持有引用的任何gen0对象都将升级到gen1;同样,如果一个不包含任何gen0引用的对象在gen1 GC中幸存,那么它包含的任何gen1引用都将被提升到gen2。因此,在gen0集合中检查对象后,除非对其进行了修改,否则在下一个gen1集合之前无需再次检查该对象。同样,在gen1集合期间检查的对象在下一个gen2集合之前无需检查,除非对其进行了修改


知道对象是否被修改是一个棘手的问题,但关键是,如果对象没有被修改,这对GC非常有利。

谁说JVM GC喜欢不可变对象?谢谢,@lichengwu,我通过添加源代码对问题进行了编辑。如果大对象在小gc期间无法放入生存区域,则可能直接升级到老一代。更糟糕的是,如果它不能适应年轻一代的自由空间,那么在创建时可能会直接升级到老一代。不可变对象有很多好处。我认为GC可以很容易地在跟踪过程中找到所有不可变的对象。我还没有弄明白如何减少照顾他们的开销。我相信Hunt提到这一点是有原因的。是的,拥有较小的不可变对象是获得最佳性能的理想情况,但他从不强调GC只支持不可变对象。我想知道是否有值得注意的GC框架对可变和不可变对象有单独的堆,附带条件是不可变堆不需要卡片表。事实上,如果你想要一个紧凑的框架,我认为如果在每个集合上扫描(但不移动)gen1/gen2可变对象,而不扫描不可变对象,那么在没有任何卡片表的情况下,你可能会获得不错的性能。谢谢,@supercat。我有问题:a)“忽略”是否意味着它不会进一步跟踪对象?b) 什么是第0代、第1代和第2代?你是说年轻人和老年人?c) GC知道对象是否被修改了吗?@Jacky:我说的“忽略”实际上是指“不再跟踪”。我主要使用.net生成0-2的数字;我认为Java实现有不止一个“年轻”和“老”代,但我不知道细节。为了让GC利用“标记”阶段中的几代,它必须知道自上一代GC以来,每一代可能修改了哪些对象。其机制相当复杂。如果有一种声明不可变对象的特殊方法,要求在引用……传递到当前执行范围之外之前指定内容,那么这些对象就不需要有与跟踪它们是否已更改相关的机制(因为它们根本不会更改);或者,在任何支持虚拟内存机制的系统上,这些机制足够复杂,可以跟踪对可变对象的更改(甚至许多系统的VM机制非常有限),这些机制可以用来确保即使是“流氓”代码也不能更改不可变对象。@Jacky:很高兴我的回答很有帮助。再想一想,对于那些不能负担卡表、但可以写保护大范围RAM的低占用虚拟机,可能每个对象的描述符中都有一点表示它将不再被写入,并让GC在下一个GC周期将该对象移动到硬件写保护区(GC本身当然可以绕过写保护)。如果在对象的构造过程中发生GC循环,它将进入一个区域,该区域中的对象必须在所有GC循环中进行扫描,但……在下一个gen1循环之前都不符合删除条件。在下一个gen1循环之后,它的“不变性”标志将使其移动到不包含任何gen0或gen1引用的写保护对象区域