三、GC算法概念

5 篇文章 1 订阅
5 篇文章 0 订阅

  在开始本章具体分析垃圾回收算法的实现之前,需要理解的是所有垃圾收集器(collector)都会关注的两个方面,

  • 找到所有存活的对象
  • 清除掉不可用对象

      在所有收集器中,都是通过标记(Marking)的方法找到存活对象的。

一、标记可访问对象

  现在JVM中所有的GC算法都是从找出存活对象开始的。下图形象的展示了JVM中各对象之间的引用关系,
  
  这里写图片描述

  首先,GC定义了一些GC Roots对象。一般来说,GC Root是由以下对象组成

  • 本地变量以及当前正在执行的方法中的输入参数对象
  • 存活的线程
  • 加载的类中的静态属性
  • JNI引用

      然后,GC会在内存中分析所有对象组成的引用图,从GC Roots开始,找到所有GC Roots对象直接或间接引用的对象,所有这些对象都被标记为存活对象。

      存活对象即上图中的蓝色小圆圈。当标记阶段结束后,每一个存活对象就已经被标记过了。那些没有被标记到的对象,即上图中的灰色圆圈,就被认为是从GC Roots不可访问的对象。这些对象会被认为是需要清理的垃圾,这些垃圾对象会在接下来的步骤中进行清除。

      在标记过程中,我们需要注意以下几点,

  • 标记过程需要暂停整个应用。因为如果在标记的同时,应用程序也在运行,对象的引用状况随时可能会发生变化,无法进行准确的标记。可以安全暂停整个应用线程(Stop The World)的地方成为安全点(safe point)。触发安全点的原因有很多种,但是到目前为止,垃圾回收导致的安全点别触发是最主要的原因。

  • 标记过程中的暂停时间长短不是由堆中的对象总数或者堆大小来决定的,而是由存活对象的多少来确定的。所以增加堆的大小并不会直接导致标记阶段暂停时间的增加。

      当标记阶段完成后,GC就会在下一阶段中将标记为不可访问的对象清除掉。
      

二、清除不再使用对象

  在不同的GC算法中,清除不再使用的对象的方法是不相同的。不同GC算法清除垃圾对象的过程大致可以分为以下几种:

  • 清除(Sweeping)
  • 整理(Compacting)
  • 复制(Copying)

1、清除(Sweep)

  标记清除(Mark and Sweep)类算法在清除不再使用对象时的策略非常简单,直接忽略掉这些对象即可。即这些算法在标记阶段结束后,那些不可访问的对象所占的内存空间就被认为是空闲的,当有新的对象需要分配空间时,直接覆盖这部分的内存。

  这种策略需要维持一个空闲列表(free-list)来记录每一个空闲区域以及该区域的大小。在为新对象分配空间时,就会记录和维护这个列表。这种策略的一个最显著问题就是这些空闲内存不连续,如果空闲内存片段中最大的区域也无法为新生成的对象分配空间时,也会报出无法分配内存的异常。
  
  这里写图片描述
  

2、整理(Compact)

  标记清除整理(Mark-Sweep-Compact)类算法则解决了上面标记清除算法的缺陷。在对不再使用的对象进行标记和清除之后,接下来会把存活的对象在内存区域中进行移动,按顺序分配在连续的内存区域中。由于需要将所有对象复制到一个新的区域并且更新指向该对象的引用,所以该策略在GC暂停上的时间消耗会更长。但是这种算法的显著优势是在后续新对象的内存分配上更加简单和高效,直接在已用内存尾部为新生成对象分配一片内存区域即可。
  
  这里写图片描述
  

3、复制(Copying)

  标记复制(Mark and Copy)类算法和标记整理算法非常类似,这两种算法都会为存活对象重新分配内存区域。两者的不同之处在于,标记复制算法为存活对象重新分配的内存区域是另一块存活区。标记复制策略的优点是,复制过程可以和标记过程同时进行,一个对象被标记为存活的同时就可以将其复制到另一片内存区域中。标记复制策略的缺点是,需要准备另一块足够容纳所有存活对象的内存区域。
  
  这里写图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值