垃圾对象的两种寻找方式
1.引用计数算法
给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加1;当引用失效,计数器就减1;任何时候计数器为0的对象就是可被回收的对象,这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题。
所谓对象之间的相互引用问题,除了对象objA和objB相互引用着对方之外,这两个对象之间再无住何引用。但是他们因为互相引用对方,导致它们的引用计数器都不为0,于是引用计数算法无法通知GC回收器回收他们。
2.根可达性算法
将"GC Roots"对象作为起点,从这些节点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未标记的对象都是垃圾对象
GC Roots根节点:线程栈的本地变量、静态变量、本地方法栈的变量等等
垃圾回收三种算法
1.复制算法
一般新生代(伊甸园区、幸存区)会使用复制算法,生成新的to区
好处:没有内存的碎片
坏处:浪费了内存空间,多了一半空间永远是空to
复制算法最佳使用场景:对象存活度较低的时候,也就是新生区
标记清除
2.标记清除
缺点:两次扫描,严重浪费时间,会产生内存碎片
优点:不需要额外的空间
3.标记整理
在标记清除上,多了一个移动成本
先标记清除一次,然后再压缩
总结
内存效率:复制算法 > 标记清除算法 > 标记压缩算法(时间复杂度)
内存整齐度:复制算法 = 标记压缩算法 > 标记清除算法
内存利用率:标记压缩算法 = 标记清除算法 > 复制算法
垃圾收集器
单线程:
新生代使用Serial GC,老年代自动使用Serial Old GC
多线程:
新生代使用Parallel Scavenge GC,老年代使用Parallel Old
这四个收集器都会产生STW,开启收集的时候,导致用户线程停止,这时候出现了CMS收集器
CMS收集器
CMS主要是为了解决STW时间过长的问题
partnew跟ps差不多,改良,能和cms搭配使用,而ps不能和cms使用
工作流程:
1.初始标记: 暂停所有的其他线程(STW), 并记录下gc roots直接能引用的对象,速度很快。
2.并发标记: 并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一 起并发运行。因为用户程序继续运行可能会有导致已经标记过的对象状态发生改变。
3.重新标记: 重新标记阶段就是为 了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一-般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短。主要用到三色标记里的增量更新算法(见下面详解)做重新标记。
4.并发清理: 开启用户线程, 同时GC线程开始对未标记的区域做清扫。这个阶段如果有新增对象会被标记为黑色不做任何处理。
5.并发重置: 重置本次GC过程中的标记数据。