深入理解JVM--垃圾收集算法
标记-清除算法
算法分为"标记"和"清除"两个阶段: 首先标记出所有需要回收的对象,在标记完成后,统一回收所有被标记的对象。
它是最基础的收集算法,会带来两个明显的问题
- 效率问题:标记和清除两个过程的效率都不高
- 空间问题:标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致在程序运行过程中需要分配对象时,无法找到足够的连续的内存而不得不提前触发另一次垃圾收集动作。
复制算法
为了解决效率问题,“复制”收集算法出现了。
它可以将可用内存按容量划分为大小相等的两快,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另一块上面,然后再把已使用过的内存空间一次清空。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。
现在的商业虚拟机都采用这种收集算法回收新生代。
标记-整理算法
根据老年代的特点特出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一段移动,然后直接清理掉端边界以外的内存。
分代收集算法
当前商业虚拟机的垃圾收集都采用"分代收集"(Denarationl Collection)算法。
这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的所以我们可以选择“标记-清理”或“标记-整理”算法进行垃圾收集。
HotSpot的算法实现
-
枚举跟节点
GC停顿:可达性分析工作必须在一个能确保一致性的快照中进行。"一致性"是指在整个执行系统看起来就像被冻结在某个时间上,不可以出现分析过程中对象引用关系还在不断变化的情况,该点不满足的话分析结果准确性就无法得到保证。这点是导致GC进行时必须停顿所有Java执行线程的其中一个重要的原因,即使是号称几乎不会发生GC停顿的CMS收集起中,枚举根节点时也是必须停顿的。
在HotSpot的实现中,是使用一组称为OopMap的数据结构来达到这个目的的,在类加载完成的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译过程中,也会在特定的位置记录下栈和寄存器中哪些位置是引用。这样GC在扫描时就可以得知这些信息类。 -
安全点
HotSpot没有为每条指令都生成OopMap,只是在"特定位置"记录类这些信息,这些位置称为安全点(Safepoint),即程序执行时并非所有地方都能停顿下来开始GC,只有到达安全点时才能暂停。
Safepoint选定既不能太少以至于GC等待时间太长,也不能过于频繁以至于过分增大运行的负荷。所以安全点的选定基本上是一程序"是否有让程序长时间执行的特征"为标准选定的,因为每条指令执行的时间都非常短暂,程序不太可能因为指令流长度这个原因而过长时间运行,"长时间执行"的最明显的特征就是指令序列复用,例如方法调用、循环跳转、异常跳转等,所以具有这些功能的指令才会产生Safeponit。
如何在GC发生发生时让所有线程(不包括执行JNI调用的线程)都在最近的安全点上才停下来。有两种方案可供选择:
1. 抢先式中断(Preemtive Suspension):不需要线程的执行代码主动去配合,在GC发生时,首先把所有线程全部中断,如果发现有线程中断的地方不再安全点上,就恢复线程让它跑到安全点上。(现在几乎没有虚拟机实现采用抢先式中断来暂停线程响应GC事件)
2. 主动式中断(Boluntary Suspension):思想是当GC需要中断线程的时候,不直对线程操作,仅仅简单地设置一个标志,各个线程执行是主动去轮询这个标志,发现中断标志为真时就自己中断挂起。轮询标志的地方和安全点是重合的。另外再加上创建对象需要分配内存的地方。 -
安全区域(Safe Regin)
安全区域是指在一端代码片段中,引用关系不会发生变化。在这个区域的任意地方开始GC都是安全的,我们可以把Safe Regin看作是被扩展了的Safepoint。
这里是引用
https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247483914&idx=1&sn=9aa157d4a1570962c39783cdeec7e539&chksm=fd98546bcaefdd7d9f61cd356e5584e56b64e234c3a403ed93cb6d4dde07a505e3000fd0c427#rd
https://www.cnblogs.com/lrh-xl/p/5292495.html