JVM-跨代索引那点事

世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。

关于跨代索引,大家也比较熟悉了,说白了就是在GC Roots的时候,需要找到老年代对新生代的引用对象,这样就可以将这个老年代对象加入的GC Roots中,以保证GC Roots枚举对象的全面与准确,同时也避免了对新生代对象的误回收操作。当然以上这些说的是传统的垃圾收集器,最新的比如ZGC是通过连接矩阵来解决跨代引用问题的。当然从根本上来说都是为了标记出跨代引用的对象,然后作为枚举对象加入到GC Roots中。当然如果每次GC Roots时搜扫描整个老年代的对象效率是不高的并且也太消耗资源。所以就提出了一个记忆集的概念。记忆集就是对老年代的一种映射,用来标记老年代中哪些对象存在跨代引用,这样在GC Roots枚举时,直接通过记忆集找到老年代的引用对象,比扫描整个老年代效率要高的多。记忆集只是一种理论概念,它的真正实现是卡表,卡表是由多个卡页组成的,每一个卡页对应老年代的一块区域,卡表会通过卡页实时的维护这些区域的引用关系,如果某个区域有一个或多个对象存在跨代引用,那么就标记为1,我们则认为这个区域变脏了,GC Roots的时候只要扫描这些变脏的区域,找到对应的引用对象加入到GC Roots枚举对象中即可。但是,卡表是如何实时维护这些跨代引用的标记的呢,如果是在纯解释的环境下,虚拟机可以实时检测出引用变化,然后同步到卡表中,但是Hotspot虚拟机存在即时编译,对于编译后的机器码再采用正常的方式就不可行了,当然还是有办法了,虚拟机提供了一个写屏障,这个写屏障就相当于java中的AOP,提供了一个环形通知,每次索引更新,都可以通过写屏障对卡表进行同步标记更新,通过这种方式,卡表就可以实时的维护跨代引用对象的引用关系了。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/a13662080711/article/details/108315150
今日推荐