GC 算法与种类
技术标签: GC 算法 JVM
文章目录
- 引用计数法
原理
图例
问题 - 标记清除
原理
图例 - 标记压缩
原理
图例 - 复制算法
原理
图例
问题 - GC算法总结
引用计数
标记-清除
标记-压缩
复制算法
标记-清除
和标记-压缩
对比 - 可触及性
可触及的
可复活的
不可触及的
经验
根 - Stop-The-World
分析
GC时为什么会有全局停顿?
危害 - 引用计数法
原理
引用计数器的实现很简单,对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1。只要对象A的引用计数器的值为0,则对象A就不可能再被使用。
问题
引用和去引用伴随加法和减法,影响性能
很难处理循环引用
-
标记清除
原理
标记-清除算法是现代垃圾回收算法的思想基础。标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。一种可行的实现是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。
图例
-
标记压缩
原理
标记-压缩算法适合用于存活对象较多的场合,如老年代。它在标记-清除算法的基础上做了一些优化。和标记-清除算法一样,标记-压缩算法也首先需要从根节点开始,对所有可达对象做一次标记。但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。
图例
- 复制算法
原理
与标记-清除算法相比,复制算法是一种相对高效的回收方法
不适用于存活对象较多的场合 如老年代
将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收
图例
问题
空间浪费
整合标记清理思想
- GC算法总结
引用计数
没有被Java采用
标记-清除
效率问题
标记和清除过程的效率都不高
空间问题
标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作
标记-压缩
优点:
堆的利用效率高
缺点:
需要多次搜索整个堆,所以,吞吐量较低(耗时较长)需要多次搜索整个堆,所以,吞吐量较低(耗时较长)
复制算法
实现简单,运行高效。只是这种算法的代价是将内存缩小为原来的一半
标记-清除 和 标记-压缩对比
标记–压缩算法的标记阶段和标记–清除算法的标记阶段是一致的,就不再重复。使用标记–压缩算法时,标记完可达对象之后,我们不再遍历所有对象清扫垃圾了,我们只需要将所有存活对象向“左”靠齐,让不连续的空间变成连续的,这样就没有内存碎片了。不仅如此,因为不再连续的空间变成连续的,内存分配也更快速了。
对于标记–清除算法来说,因为内存中有碎片,空闲内存不再连续,为了分配内存,系统内可能要维护着一个空闲内存空间的链表。当需要分配内存时,会遍历这个链表,找到一个够大的内存块,然后将其分成两份,一份用作当前的分配,另一份放回链表(这样有造成更多的内存碎片,也有一些策略并不是按顺序查找,找到够大的就好,有可能是找到一个更好的空闲内存块为止)。而对于标记–压缩算法,内存空间是连续的,我们只需要一个指针标记出下一次分配工作要从哪里开始就可以了,分配后将指针递增所分配对象的大小,这个工作是非常快速的,而且不用维护那个空间内存链表了。
这样一看好像标记–压缩算法绝对的优于标记–清除算法,那标记–清除还有啥存在的必要了呢?不过要记住的一点是标记–压缩算法为了达到压缩的目的,是需要移动对象的,这会有性能消耗的,这样所有对象的引用都必须更新。看来有利必有弊。
所有的算法,需要能够识别一个垃圾对象,因此需要给出一个可触及性的定义
- 可触及性
可触及的
从根节点可以触及到这个对象
可复活的
一旦所有引用被释放,就是可复活状态
因为在finalize()中可能复活该对象
不可触及的
在finalize()后,可能会进入不可触及状态
不可触及的对象不可能复活
可以回收
经验
避免使用finalize(),操作不慎可能导致错误
优先级低,何时被调用, 不确定,何时发生GC不确定,可以使用try-catch-finally来替代它
根
栈中引用的对象
方法区中静态成员或者常量引用的对象(全局对象)
JNI方法栈中引用对象 - Stop-The-World
分析
Java中一种全局暂停的现象
全局停顿,所有Java代码停止,native代码可以执行,但不能和JVM交互
多半由于GC引起
Dump线程
死锁检查
堆Dump
GC时为什么会有全局停顿?
类比在聚会时打扫房间,聚会时很乱,又有新的垃圾产生,房间永远打扫不干净,只有让大家停止活动了,才能将房间打扫干净。
危害
长时间服务停止,没有响应
遇到HA系统,可能引起主备切换,严重危害生产环境