0. 分代收集
当前大多数商业虚拟机的垃圾收集器都遵循“分代收集”。就是针对不同的内存区域使用不同的数计算法。但是已经有能够全区域收集不分代的收集器了。
未来会不会不分代的虚拟机主导呢,真是的,@_@学习的速度赶不上技术发展的速度。。。
-
部分收集(Partial GC):不是针对完整的 java 堆的垃圾收集
- 新生代收集(Minor GC / Young GC):只针对新生代的垃圾收集
- 老年代收集(Major GC / Old GC):只针对老年代的垃圾收集
- 混合收集(Mixed GC):针对
整个新生代
+部分老年代
的垃圾收集
- 整堆收集(Full GC):针对整个 java 堆区的垃圾收集
以下内容忽略标记算法,只针对收集。
1. 标记-清除算法
他是最早、最基础的收集算法,分为两个阶段:标记
和清除
。
就是第一阶段先标记需要回收的对象(或者不需要回收的对象),然后由第二阶段统一回收。
缺点:1. 随着对象增多,效率降低;2. 清除过后遗留空间碎片
2. 标记-复制算法
将内存一分为二(暂称 A,B),对象存在其中一个区域 A 中,当垃圾收集时,将 A 区的存活对象复制到 B 区(依次贴合),然后把 A 区清空。
优点:
- 分配内存只需按顺序分配即可,实现简单、运行高效;
- 没有空间碎片;
- 只有少数存活对象时,复制开销小(多数对象都是“朝生夕死”,所以很适合新生代)
缺点:
- 总是有一半空间需要空闲着,空间浪费严重
- 存活对象多的时候,复制成本较大
3. 标记-整理算法
× 本来一直以为,这个算法是 标记、清除、整理三个阶段。原来根本是这么回事儿。。。×
应该是标记
、移动
,清除
三个阶段。
第一阶段标记,和“标记-清除算法”一样;
第二阶段,是将所有存活对象向着内存的一端移动(标记-清除算法是没有移动的),存活对象都堆在一起之后,进行下一阶段;
第三阶段,将存活对象边界以外的内存清除掉。
优点:
- 没有空间碎片,分配内存方便
缺点:
- 每次都要移动所有存活对象,负担极大
- 需要暂停用户线程,Stop The World
标记-整理 VS 标记-清除
标记-整理算法,在回收过程中,需要移动对象,更复杂,而且需要较长停顿时间,但是分配内存会更方便。但是从程序整体吞吐量看,它比“标记-清除算法”划算,也就是说它侧重整体吞吐量
。Parallel Scavenge 收集器才用的就是这种算法。
标记-清除算法,相反的,不需要移动对象,回收相对简单,停顿时间更短甚至不需要停顿,延迟低。但是由于产生空间碎片,使得分配内存更加复杂,吞吐量下降。所以它侧重的是延迟
。CMS 收集器使用的是这种算法。
所以,还没有完美的 GC 算法,垃圾收集器根据各自的侧重点选择“标记-整理”还是“标记-清除”,还有的是混合的。CMS 收集器在碎片不多的时候采用 “标记-清除”,碎片过多就会采用 “标记-整理”。
网友评论