浅谈Java虚拟机垃圾收集算法的研究和改进论文
1 垃圾收集基本算法研究和当前的瓶颈
垃圾收集器的核心是识别和回收不可到达的对象,不同的垃圾收集实现使用不同的策略来完成,它们与用户程序和调度器以不同的方式互动。有几种垃圾收集的基本策略: 引用计数、标记—清除、标记—整理和复制。此外,还可以按照系统运行方式来分类算法,串行收集必须在用户程序暂停时进行整个收集,并行或并发收集是使用多线程进行收集来提高效率。
1. 1 垃圾回收基本算法研究
引用计数是最基本的垃圾收集策略,早期的JVM 采用此算法,但是缺点也很明显,如它不能回收不可到达的循环结构以及需要监控每一次的内存操作; 标志—清除算法主要包括扫描标志所有被应用对象,然后清除未引用对象两个步骤,最大的不足是执行时需要暂停整个程序,以及容易在堆中产生碎片; 复制算法创新地提出把堆一分为二,其中一个区域包含当前使用的活跃的数据,另一个区域未使用,垃圾回收时,遍历当前已经使用的有相关活跃对象的区域,把正在使用中的对象从当前区域复制到另外一个区域中,性能好,而且不会有碎片,主要问题就是必须要两倍的内存空间; 标记—整理算法则是结合了标记—清除和复制这两个算法的优点,避免了需要两倍内存空间的问题,但增加了不少复杂性,该算法也是分两阶段,第一阶段从对象根节点开始标记所有被引用对象,第二阶段遍历整个堆,清除未标记对象并且把存活对象“压缩”到堆的其中一块,按内存顺序排放; 分代收集利用统计学分析的方法来提高效率,分析表明大多数内存块( 90%) 的生存周期都比较短,垃圾收集器应当把更多的精力放在检查和清理新分配的内存块上,它是基于对象的生存周期统计分析后得出的算法,把对象分为年青代( 年轻的新生对象) 、年老代( 经过几次回收仍然存活的对象) 、持久代( 静态文件、JAVA 类、方法等) ,对不同生命周期的对象使用不同的算法( 如标记整理) 进行回收。
1. 2 垃圾回收的瓶颈
经过不断的算法创新和改进,垃圾回收方式已经在内存空间效率和CPU 时间效率两个方面有了非常大的提升。但仍然无法解决完全GC 带来的暂停问题。在一些对实时性要求很高的应用情形下( 如期望返回时间在几百毫秒以内),如果分代垃圾回收方式要达到这个指标,只能把最大堆的设置限制在一个较小范围内,但是这样又和应用本身的处理能力产生很大的矛盾,同样也是不能接受的。即垃圾收集的周期,以及每次收集的时间还是不确定。
2 新改进的算法
新改进的算法主要目标是在不牺牲堆空间利用效率和CPU 性能的前提下达到准实时( 可以设定和控制GC 最大暂停时间) ,如0. 5 秒。这个特性对于准实时响应的系统( 如电信系统) 而言非常重要,因为这样就再也不用担心系统会突然暂停两秒这种情况的发生了。
为了能够达到期望的目标,新的`算法在原有的各种算法上进行了吸收和改进,第一方面: 新算法吸收了增量GC,将整个虚拟机堆划分为多个固定大小的区域[5],这样通过先在空间维度上的划分,然后在小粒度上处理收集的方法,为实现整个实时性目标打下一个基础。第二方面,采用了并发的快照扫描算法,进行全局范围的未到达对象周期性完整扫描。同时扫描时统计了每个小区域中的活跃对象。这个信息帮助后续选择哪一个区域进行回收。第三方面,采用新的选择回收机制估算区域级垃圾回收时间,然后根据限值选择相应的区域。
2. 1 新算法堆分区和区域结构
新算法将堆划分为多个固定大小的区域,每个区域都是在内存中一块连续的区域。当一块区域放满后,会申请新的一块区域来存放,空的区域用链表结构组织起来。区域之间的对象引用通过“关系集合”来维护,对于巨大的对象,如超过一个区域的一半以上,用专用的一个堆来处理这类对象。每个区域都有一个关系集合,关系集合中包含了从其他区域中引用当前区域中相关对象的引用地址,随着程序的操作,新引用或解除当前区域中的一个对象都会在关系集合中做出相应的修改。这个关系集合主要维护跨区域的对象引用联系。区域1,3中都引用了区域2 的对象b,所以区域2 关系集合中维护了相应的关系。这些区域中对象的引用关系不断地发生改变,新算法采用了卡片表来通知区域修改“关系集合”,每个应用的线程都有一个关联的关系集合记录,用于缓存和顺序化线程运行时造成的对于卡片的修改。另外,还有一个全局的缓存区,当应用线程执行时修改了卡片后,如果造成的改变仅为同一区域中的对象之间的关联,则不记录关系集合历史; 如造成的改变为跨区域中的对象的关联,则记录到线程的关系集合历史; 如线程的关系集合历史满了,则放入全局的缓存区中,线程自身则重新创建一个新的关系集合历史,关系集合本身也是一个由一堆卡片构成的哈希表。
下面是具体垃圾回收执行步骤。
2. 2 初始化标记
这是第一个步骤,支持多线程并发执行。主要任务是扫描并标识出虚拟机每个区域中可直接访问到的对象。虚拟机每个区域都保存了两个标识作用的位图,位图中每个元素用来标识可到达的对象。一个名称为最近引用的位图,用来保存最近扫描标志的结果。另外一个为当前引用位图,用来存放当前正在计算的临时结果。当计算完成时,会把结果复制到最近引用位图中。位图中包含了一个地址信息来指向区域中对象的起始点。
新算法设定了相关的条件来触发初始化标记这一步骤。定义了一个虚拟机堆大小的上限,称为high,另外还有一个H,H 的值为( 1-high) * 堆大小,根据虚拟机的运行情况进行动态的调整,如果引入分代方式,新算法还定义了一个限值,当堆中使用的内存超过了限值时,就会在一次清除执行完毕后在应用允许的GC 暂停时间范围内尽快地执行此步骤。
2. 3 遍历并发标记
根据前面初始化标记扫描到的对象进行遍历,以便识别这些对象的下层对象的活跃状态,对于在此期间应用线程并发修改的对象则记录到关系集合历史中,采用开始时刻点快照的方式进行对象遍历。这一过程是并行执行的,不会暂停应用程序线程。应用程序线程新创建的对象则放入比快照顶端值更高的地址区间中,这些新创建的对象默认状态即为活跃的,这一过程同时修改顶端值的信息。这样的设计不仅可以不影响应用程序,而且提高了效率。由于是并行的环境,在做并发标记扫描时还需要处理一种情况,就是其他程序修改当前快照里的对象应用。系统允许这样的修改,但是需要记录这样的修改到后续步骤处理它。
2. 4 标记停止
标志停止这个点除了需要满足遍历所有对象和清空当前的标志堆栈事件这两个条件外,还需要处理前面一步由于其它线程的修改保留下来的记录。前面两个条件容易判断,后一个条件处理比较困难。因为这些记录放在相关的线程中,需要等待相应线程操作结束后处理,有可能会引起一些等待。
2. 5 存活计算活对象和清除
前面有提过采用新的机制为了达到准实时目标。主要的算法根据前面统计的活跃对象数,设计算法比较精确地估算出每个区域的垃圾回收时间,如公式( 1) 所示。同时根据系统设定的目标最大暂停时间,来选择活跃对象最少、垃圾对象最多、收集最快的区域进行回收,这样能保证最有效率,而且暂停时间最短。如果超过设定的目标最大暂停时间,系统会推迟收集来权衡目标,通过一段时间,会有更多的非活跃对象。
C( tc) = Cfix + A* N +Σr∈tc
( T* size( r) +
S* active( r) ) ( 1)
tc 表示收集当前区域估算所需时间成本,C 表示固定的一些步骤开销。A 表示扫描卡片的平均时间,N 表示卡片数量,T 表示从关系结合中扫描出卡片的时间, size( r) 表示在关系集合r 中卡片数。S表示每个字节的扫描成本,active( r) 表示当前区域r中的存活字节数量。
在新算法中,标记停止步骤执行完,不一定会执行清除这一步骤,由于清除步骤需要暂停应用对系统有一定的影响,新算法为了能够达到准实时的要求,需要根据用户指定的最大的GC 暂停时间设定和公式( 1) 估算出的时间成本相结合来合理地规划清除动作。另外还有一些情况也会触发清除这个步骤的执行,如新算法在采用复制方法的特殊步骤情形下,采取的是当已经使用的内存空间达到了上__限时,就执行清除这个策略以保证有足够的空间用来做复制动作。再比如新算法在分代模式的情形下,根据用户指定的可接受的暂停时间和回收年轻代区域需要消耗的时间来估算出一个年轻代区域存活的数量的最大值,当虚拟机中分配对象的年轻区域存活的数量达到此值时,就会执行清除。
在这一过程中,在一些特定的情形下,会采用疏散压缩的计算来提高效率,主要是针对比较新的计算。比如说发现绝大部分当前区域的对象可以被回收掉,会立刻执行回收清除动作,然后剩下的对象疏散到其他区域,这样的动作非常大地提高了效率,而且支持并发执行。这样在多处理器的环境下更能提高效率。
运用新算法是为了尽量做到准实时的响应,例如估算暂停时间的算法、对于经常被引用的对象的特殊处理等,运用新算法也是为了能够让GC 既能够充分地回收内存,又能够尽量少地导致应用的暂停。
3 实验结果与分析
通过在几种典型的准实时应用场景中进行实验,对新算法和增量式垃圾回收算法在垃圾回收效率、平均暂停时间、暂停次数及堆空间使用等方面进行比较。运用新算法后各方面都有比较大的性能提升。新算法使用C 语言实现,而增量式垃圾回收算法直接使用Sun JDK 提供的算法。实验的应用场景包括一个大型的游戏应用和一个企业级的产品管理系统。同时还可以根据应用的情况,调节参数使系统达到比较好的状态。
4 结束语
为了实现准实时的目标,本文提出了一种新的垃圾回收算法,在堆空间划分、并发扫描及区域垃圾回收成本等方面做了很大的改进,将因垃圾收集而导致的程序暂停时间和次数限制在一个可以设定的范围内,并可以通过相关的配置参数的调节,达到一个在时间和空间成本比较高效率的状态,满足了实时性应用所要求的短暂停,并且在应用环境下取得了令人比较满意的效果,这对于有巨大缓存的各种应用而言,会有很大的帮助。
【浅谈Java虚拟机垃圾收集算法的研究和改进论文】相关文章: