为什么堆被划分为Eden、Survivor 空间和Old Generation?

6 java garbage-collection jvm heap-memory g1gc

你能回答我一个关于 JVM 垃圾收集过程的问题吗?

为什么堆被划分为Eden、Survivor 空间和Old Generation?

当一个年轻的疏散被处理时,通过从根开始的引用来访问对象以找出无法访问的对象。可到达的对象被标记为“活着”,不可到达的对象不被标记并将被消除。

结果,所有对象都被考虑,包括在老年代分配的对象也被访问并标记,如果它们是可达的。

据我所知,同时回收年轻代和老年代是很困难的,因为这些代位于内存的不同连续部分。

但是,如果即使在 Young 疏散级别上最简单的标记之后,如果所有可到达和不可到达的对象都是已知的并且可以删除,我们仍然拥有包含所有活动和死对象的整个位图,为什么我们需要这种划分?

我也知道弱世代假设,但为什么我们需要划分?

Hol*_*ger 3

基本前提是,当创建新对象时,不存在从旧对象到新对象的引用,并且对于很多对象,甚至大多数对象来说,这永远不会改变。这意味着,如果您可以证明仍然没有从旧对象到新对象的引用,或者当您确切知道哪些引用时,您可以仅对年轻代进行 \xe2\x80\x9cminor\xe2\x80\x9d 垃圾收集扫描已被创建。

\n

这意味着必须跟踪和记住对旧对象的引用更改(但请记住这样的更改不会经常发生的前提)。

\n

一种实施策略是卡片标记

\n
\n

如果垃圾收集器不收集整个堆(增量收集),则垃圾收集器需要知道哪里有从堆的未收集部分到正在收集的堆部分的指针。这通常适用于分代垃圾收集器,其中堆中未收集的部分通常是老年代,而堆中已收集的部分是年轻代。用于保存此信息(老年代指针指向年轻代对象)的数据结构是一个记忆集。牌桌一种特殊类型的记忆集。Java HotSpot VM 使用字节数组作为卡表。每个字节称为一张。一张卡对应于堆中的一个地址范围。脏卡意味着将字节的值更改为脏值;脏值可能包含卡覆盖的地址范围内从老年代到年轻代的新指针。

\n

处理卡意味着查看卡以查看是否存在老一代到年轻代的指针,并且可能对该信息执行某些操作,例如将其传输到另一个数据结构。

\n
\n

当然,如果使用世代能够让我们在扫描过程中跳过某些内存区域,并且维护这些记住的集合不会超过节省的成本,那么使用世代只会带来好处。

\n