上一篇关于《Java垃圾收集之追踪器》文章主要把Java垃圾收集相关概念概述了一下,同时大概总结了一下垃圾收集算法中的计数器算法,但是由于计数器算法存在很多缺点,所以目前在Java垃圾收集中已经不使用此算法,目前主要使用追踪算法,下面就总结和温故一下追踪算法相关概念。
跟踪收集器:
跟踪收集器追踪从根节点开始的对象引用图,在追踪过程中对活动对象打上标记。总的来说要么在对象本身设置标记,要么用一个独立的位图来设置标记,当追踪结束时,未被标记的对象就是无法触及的,从而可以被收集。
基本的追踪算法被称作“标记并清除”。这个名字指出垃圾收集的两个阶段。标记阶段,垃圾收集器遍历引用树,为遍历到对象增加标记,清除阶段,把没有被标记的对象清除,释放其占用的内存空间,在JVM中清除对象必须包含对象的终结。
压缩收集器:
Java虚拟机的垃圾收集可能有对待堆碎片的策略。通常是压缩和拷贝。这两种方法都是快速移动对象来减少堆碎块。
处理堆碎块步骤如下:
把活动对象越过空闲区移到堆另一端 -> 堆的另一端出现连续空闲区 -> 跟新所有被移动对象引用指向(因为对象位置改变了)注:通过引入句柄表的概念,让对象所有引用指向句柄表,当对象位置改变之后直接改变句柄表的引用,这样不需要更改所有引用的指向,提高性能。
拷贝收集器:
拷贝收集器把所有活动对象移到一个新的区域,在拷贝过程中,它们被紧挨着布置,所以可以消除它们在旧区域的空隙。
一般拷贝收集器算法被称为“停止并拷贝”,在这个方案中堆被分为两个区域,任何时候都只使用其中的一个区域,对象在同一个区域中分配,直达这个区域被耗尽,此时程序被终止,堆被遍历,遍历时遇到活动对象被拷贝到另外一个区域,当停止和拷贝过程结束时,程序恢复执行,内存将从新的堆区域中分配,知道它也被耗尽。这个方法缺点就是:对于指定大小的堆来说需要两倍的内存,因为任何时候都只能使用其中一个。
一下这个图详细记录了拷贝收集的过程:
按代收集的收集器:
从上边停止并拷贝算法可以看到一个缺点就是:
1. 大部分程序创建很多生命周期很短的对象。
2. 大部分程序都有生命周期很长的对象。
简单拷贝如果来回拷贝这些生命周期很长的对象无疑是浪费了很多时间,而按代收集概念就是,对简单拷贝的模型进行再次细化,可以根据对象不同生命周期进行划分,以此提高效率。
自适应收集器:
场景就是在某些情况下,某些垃圾收集器可以工作的更好,而来另外场景下令一种垃圾收集器算法可以工作更好,自适应算法监视堆中的情形,并且对应的调整合适的垃圾收集技术。
火车算法:
垃圾收集算法和明确释放对象比起来有一个潜在缺点,即垃圾收集算法中程序对安排CPU时间进行内存回收缺乏控制。要精确预算出合适进行垃圾收集,收集需要多长时间几乎是不可能的。
如果一种垃圾收集算法可能导致用户可察觉得到的停顿或者使得程序无法适合实时系统的要求,这种算法被称作破坏性的。
设计垃圾收集算法一个基本目标就是使本质上的破坏性尽可能小,如果可能的话尽可能消除这种破坏性。
达到(或试图达到)非破坏垃圾收集的方法是使用渐进式收集算法。渐进式垃圾收集器不一次性收集完不可触及对象,而是每次只收集一部分,因此理论上说每次时间都会很短,每次收集可以保证不超过一个最大时间长度,就可以让Java虚拟机适合实时环境。
通常渐进式垃圾收集器都是按代收集的收集器。