【理解HotSpot虚拟机】串行垃圾收集器Serial和Serial Old原理

转载请注明出处:http://blog.csdn.net/linxdcn/article/details/78154133


上一篇GC垃圾收集器的对比分析分析和对比了JVM中常见的垃圾收集器,本篇先来探究串行垃圾收集器的原理。


1 Serial 收集器

Serial 收集器是在 DefNewGeneration 新生代上实现收集的,DefNewGeneration上分为3个区:eden 区、 from区和 to 区。Serial 收集器使用复制算法进行回收复制算法的思想是将eden和from区活跃的对象复制到to区,并清空eden区和from区,如果to区满了,那么部分对象将会被晋升移动到老年代,随后交换from和to区。

假设我们有如下状态的 DefNewGeneration 需要收集:



Step 1

遍历当前内存代中所有根对象,eden和from区的根对象将被复制到to区,形成T0对象集



复制eden的根对象

Step 2

遍历更低内存代(DefNewGeneration无更低内存代)和更高内存代对象(TenuredGeneration)所有对象(实际中无需遍历所有,而是通过Card Table解决),如果这些对象有引用当前内存代的对象,则把对象复制到to区,形成T0对象集



遍历其他内存代的对象

Step 3

通过广度优先搜索算法遍历扫描活跃对象,即T0对象集



从T0集合开始广度优先算法

Step 4

如果Eden区中的对象的age达到_tenuring_threshold,则不是将对象复制到to区,而是提升到高一代(TenuredGeneration)



6号对象的age超过_tenuring_threshold

Step 5

如果to区满了,eden区中的存活对象也将被提升到高一代(TenuredGeneration)



7号对象因to区满了也提升到Old区

Step 6

  1. 清除eden区和from区
  2. 交换from区和to区地址

小结

  • 进行GC前需要确定(1)to区为空;(2)下一个内存代有足够的内存容纳新生代的所有对象
  • Step 1 - Step 3被称为可达性分析

2 Serial Old 收集器

Serial Old 收集器是在 TenuredGeneration 老年代上实现收集的,Serial Old 收集器 所使用的垃圾回收算法是标记-压缩-清理算法。在回收阶段,将标记对象越过堆的空闲区移动到堆的另一端,所有被移动的对象的引用也会被更新指向新的位置。

假设我们有如下状态的 TenuredGeneration 需要收集:



Step 1 递归标记所有活跃对象

与DefNewGeneration类似,以

  • 当前内存代中所有根对象
  • 在当前代中,被更低内存代(DefNewGeneration)和更高内存代对象(TenuredGeneration无更高代)任意对象引用的当前内存代的对象

为初始集合,采用广度优先算法查找当前代中的存活对象



Step 2 计算所有活跃对象在压缩后的偏移地址

遍历所有的对象,为存活对象重新计算新对象的地址,并将新地址设置为存活对象的转发指针



Step 3 更新对象的引用地址

遍历各内存代对象/引用,若对象所引用的对象已经被标记,则更新其引用地址为转发指针所转向的新地址。



Step 4 移动所有活跃/存活对象到新的位置

遍历TenuredGeneration对象,对于存活对象,复制原对象的数据内容到压缩后的地址(即转发指针的地址),并初始化新的位置的对象的MarkWord



小结

  • 用广度优先方法作可达性时,DefNewGeneration 是用to区来保存结果,而 TenuredGeneration 是用一个临时stack来保存结果
  • 标记对象:设置对象的对象头为被标记状态,有些对象的对象头可能包含一些信息,需要在GC结束之后进行恢复,所以标记前需保存对象和对应的对象头

3 参考

http://www.cnblogs.com/iceAeterNa/p/5028155.html
http://www.cnblogs.com/iceAeterNa/p/4878112.html


转载请注明出处:http://blog.csdn.net/linxdcn/article/details/78154133

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页