分代收集
目前的垃圾回收器大多都遵循“分代收集”的理论进行设计,收集器将java堆划分出不同的区域,然后将回收对象依据年龄(存活对象经历的垃圾回收次数)分配到不同的区域之间存储。
目前虚拟机里一般将堆分为新生代和老年代。新生代在每次垃圾回收时都会有大量对象死亡,而存活的对象会逐步晋升到老年代。
分代的好处是垃圾回收器可以每次只回收堆内部分区域。同时针对不同区域对象的特点(垃圾对象数量)使用不同的垃圾回收算法进行有效回收。
根据每次回收的区域不同将回收分为:Minor GC,Major GC,Mixed GC,Full gc.
Minor GC (minor 英[ˈmaɪnə(r)]) 也称为 Young GC.指只对新生代进行垃圾回收。
Major GC (major 英[ˈmeɪdʒə(r)]) 也称为Old GC.指只对老年代进行垃圾回收。
Mixed GC 混合收集,指对整个新生代和部分老年代进行收集。目前只有G1收集器有这种操作。
Full GC 整堆收集,指对整个新生代和老年代以及方法区进行收集。
当进行了分代操作后,在垃圾回收时会存在一个跨代引用的问题。例如新生代引用了老年代,或老年代引用了新生代,在单独收集某一代时会出现不得不扫描另一代的问题。所以如果只进行部分区域垃圾回收时,都会存在跨代引用问题。
当收集新生代时,我们可能要对老年代全盘扫描的问题。由于这种跨代引用的对象理论上是非常少的,所以在新生代上建立了一个全新的数据结构:Remembered Set.这个结构把老年代分成若干小块。记录老年代的哪一块内存存在引用新生代的跨代引用(在对象增加引用关系时维护)。在新生代垃圾回收时,在包含跨代引用的老年代对象会被加入到GC Roots扫描。这样在垃圾回收时比全盘扫描老年代性能上要好一些。
Remembered Set具体实现方式是目前常用的Card Table(卡表) 形式。它其实是一个byte数组。字节数组中每个元素对应标识的内存区域中的一块特定大小内存块,被称作Card Page(卡页),卡页大小一般为2的N次幂。HotSpot中使用的是2的9次幂,即512字节。一个卡页中包含多个对象,当其中一个对象中字段存在跨代指针,就将该卡页值标识为1(卡页变脏Dirty),反之则为0,当垃圾收集时,筛选出为1的元素,加入GC Roots扫描。
网友评论