题目:什么是跨代引用,有什么问题?
难度:low
标签:jvm/gc, general/knowledge, difficulty/low
评分:⭐⭐☆☆☆(2/5)
跨代引用指的是年轻代的对象引用了老年代的对象,或者老年代的对象引用了年轻代的对象,这时候年轻的对象进行ygc的时候无法正常回收,没法回收老年代的空间,导致空间无法正常释放,对象可能会直接从年轻代进入老年代
优点:
不足:
补充:跨代引用是单向的(Old→Young),通过 Remembered Set/Card Table + 写屏障解决。
核心考点定位:考察对跨代引用的严格定义、问题本质和解决机制的理解。
知识点拆解:
考察方向:
延伸递进面试题:
【一句话结论】
面试官您好,跨代引用特指老年代对象引用新生代对象,FullGC 时若全堆遍历会 O(n) 爆炸,通过 Remembered Set/Card Table + 写屏障解决。
【三点展开】
第一,跨代引用是单向的,特指 Old→Young 引用,不是双向的。Young→Old 引用是正常的,FullGC 时会扫描。问题只在 Old→Young:FullGC 时若从老年代 GC Roots 遍历新生代,需要扫描整个新生代,O(n) 爆炸(新生代通常 1/3 堆大小)。
第二,解决机制有两种:G1 用 Remembered Set,每个老年代 Region 维护一个跨到年轻代的引用集合,FullGC 时只扫描这些集合里的引用,避免全堆遍历。CMS/Parallel 用 Card Table,每 512 字节标记一个 Card,写屏障在对象引用赋值时更新 Card 状态,FullGC 时只扫描"脏"的 Card。
第三,写屏障是关键:对象引用赋值时插入的检查代码,如果新引用指向新生代对象,更新 Card Table 或 Remembered Set。这样 GC 可以高效处理并发修改,避免全堆扫描。
【一句边界】
当然,跨代引用不是双向的。Young→Old 引用是正常的,FullGC 时会扫描。问题只在 Old→Young,因为从老年代 GC Roots 遍历新生代会 O(n) 爆炸。另外,G1 的 Region 设计让跨代引用问题更容易管理(Remembered Set 按 Region 维护)。