JavaGC垃圾回收机制和常见垃圾回收算法

Java GC是在何时,对什么东西,作了什么事情?”程序员

 

什么位置:大部分在还有方法区!!方法区的垃圾收集主要回收两部份内容:废弃常量无用的类,当满了以后一样触发FullGC, HotSpot1.8以前由永久代实现,1.8已经移到元空间元空间并不在虚拟机中,而是使用本地内存算法

 

何时:程序员不能控制具体时间,系统在不可预测的时间调用System.gc()函数的时候;固然能够经过调优,用NewRatio控制newObject和oldObject的比例,用MaxTenuringThreshold 控制进入oldObject的次数,使得oldObject 存储空间延迟达到full gc,从而使得计时器引起gc时间延迟OOM的时间延迟,以延长对象生存期。并发

 

什么东西:超出了做用域或引用计数为空的对象;从gc root开始搜索找不到的对象,并且通过一次标记、清理,仍然没有复活的对象。ide

 

什么事情:删除不使用的对象,回收内存空间;运行默认的finalize,固然程序员想马上调用就用dipose调用以释放资源如文件句柄,JVM用from survivor、to survivor对它进行标记清理,对象序列化后也可使它复活。函数

 

引用计数法和可达性分析算法

引用计数法(ReferenceCounting):给对象中添加一个引用计数器,每当它被引用到一个地方时,计数器值就+1,;当引用失效时,计数器值就-1;任什么时候刻计数器为0的对象就是不可能在被使用spa

1)、优势.net

断定效率很高线程

(2)、缺点xml

不会彻底准确,由于若是出现两个对象相互引用的问题就不行了。对象

就像JVM问A能够被回收不,A说我被B引用去问B;

JVM问B能够被回收不,B说我被A引用去问A。

如今虚拟机都不采用引用计数法

 

 

可达性分析法:该方法的基本思想是经过一系列的GC Roots对象(局部变量,栈等)做为起点进行搜索,若是在“GC Roots”和一个对象之间没有可达路径,则称该对象是不可达的,不过要注意的是被断定为不可达的对象不必定就会成为可回收对象;被断定为不可达的对象要成为可回收对象必须至少经历两次标记过程,若是在这两次标记过程当中仍然没有逃脱成为可回收对象的可能性,则基本上就真的成为可回收对象了。

 

GC Roots的对象

  • 虚拟机栈(帧栈中的本地变量表)中引用的对象
  • 方法区静态属性引用的对象。
  • 方法区常量引用的对象。
  • 本地方法栈 JNI 引用的对象。

 

Stop The World

可达性分析期间须要保证整个执行系统的一致性,对象的引用关系不能发生变化,因此须要将用户的正常的工做线程所有停掉,避免对象的引用关系变化,与可达性分析不一致

 

致使GC进行时必须停顿全部Java执行线程(称为"Stop The World");(几乎不会发生停顿的CMS收集器中,枚举GC ROOTS时也是必需要停顿的)

      是JVM在后台自动发起自动完成的;

      在用户不可见的状况下,把用户正常的工做线程所有停掉;

 

 

垃圾回收算法

标记-清除(Mark-Sweep)算法两个阶段标记阶段和清除阶段。标记阶段的任务是根据GC ROOTS标记出全部须要被回收的对象,清除阶段就是回收被标记的对象所占用的空间;标记-清除算法实现起来比较容易,可是有一个比较严重的问题就是容易产生内存碎片,碎片太多可能会致使后续过程当中须要为大对象分配空间时没法找到足够的空间而提早触发新的一次垃圾收集动做。

 

 

复制算法它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另一块上面,而后再把已使用的内存空间一次清理掉,这样一来就不容易出现内存碎片的问题。

 

 

标记-整理算法:应用在老年代该算法标记阶段和Mark-Sweep同样,可是在完成标记以后,它不是直接清理可回收对象,而是将存活对象一端移动,而后清理掉端边界之外的内存。在清理的时候,把全部 存活 对象扎堆到同一个地方,让它们待在一块儿,这样就没有内存碎片了。

 

 

分代收集算法(目前经常使用):应用在年轻代根据对象存活的生命周期将内存划分为若干个不一样的区域通常来讲是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将EdenSurvivor中还存活的对象复制到另外一块Survivor空间中,而后清理掉Eden和刚才使用过的Survivor空间。

 

 

 

分代收集算法总结:

(1)在年轻代中,Eden区提供堆内存若是了,Eden进行MinorGC将存活的对象Survivor A中,Eden区清空

2)Eden再次 Eden 区和 Survivor A 区同时进行 Minor GC,把存活对象放入 Survivor B 区,Eden和Survivor A同时清空;

(3)重复2)的操做,若是当某个 Survivor 区被填满,且仍有对象未被复制完毕时,或者某些对象在反复 Survive 15 次左右时,或者大对象,则把这部分剩余对象放到Old 区(老年代)

(4)当 Old 区也被填满时,进行 Full GC,对 Old 区进行垃圾回收。

 

[注意,在真实的 JVM 环境里,能够经过参数 SurvivorRatio 手动配置 Eden 区和单个 Survivor 区的比例,默认为 8。能够经过参数–XX:SurvivorRatio 来设定,即将堆内存中年轻代划分为8:1:1]

 

常见垃圾回收器:

CMS

 

CMSConcurrent Mark-Sweep Collector)收集器是一种以获取最短回收停顿时间为目标的收集器,它是一种并发收集器,采用的是Mark-Sweep算法。

一种以获取最短回收停顿时间为目标的收集器标记-清除,有 4 个过程:

初始标记(查找直接 gc roots 连接的对象),须要“Stop The World”;

并发标记GC Roots Tracing 过程:查找与gc roots非直接相连的对象,以GCRoots的对象做为起始点,从这个节点向下搜索,搜索走过的路径称为ReferenceChain,当一个对象到GCRoots没有任何ReferenceChain相连时,这个对象不可到达,则证实这个对象不可用

从新标记(因 并发标记时有用户线程在执行,标记结果可能有变化),须要“Stop The World

并发清除(并发清除阶段会清除对象

 

其中初始标记和从新标记阶段,要stop the world(中止工做线程)

 

优势并发收集,低停顿

 

缺点

1 能处理浮动垃圾 

2)对 cpu 资源敏感,占用CPU资源较大。CMS默认启动的回收线程数是(CPU数量+3)/ 4,也就是当CPU在4个以上时,并发回收时垃圾收集线程很多于25%的CPU资源,而且随着CPU数量的增长而降低。可是当CPU不足4个(譬如2个)时,CMS对用户程序的影响就可能变得很大

 3)产生大量内存碎片

 

G1

 

G1收集器是面向服务端应用的收集器,它能充分利用CPU多核环境。

所以它是一款并行并发收集器,而且它能创建可预测的停顿时间模型。

垃圾回收进行了划分优先级的操做,这种有优先级的区域回收方式保证了它的高效率;最大的优势是结合了空间整合不会产生大量的碎片,也下降了进行gc的频率,让使用者明确指定停顿时间。

 

初始标记(Initial Marking) 
初始标记阶段仅仅只是标记一下GC Roots直接关联到的对象,而且修改TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的Region中建立新对象,这阶段须要停顿线程,但耗时很短。

并发标记(Concurrent Marking) 
并发标记阶段是从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行。

最终标记(Final Marking) 
最终标记阶段是为了修正在并发标记期间因用户程序继续运做而致使标记产生变更的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remembered Set Logs里面,最终标记阶段须要把Remembered Set Logs的数据合并到Remembered Set中,这阶段须要停顿线程,可是可并行执行。

筛选回收(Live Data Counting and Evacuation) 
筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所指望的GC停顿时间来制定回收计划,这个阶段其实也能够作到与用户程序一块儿并发执行,可是由于只回收一部分Region,时间是用户可控制的,并且停顿用户线程将大幅提升收集效率。

 

 

https://baijiahao.baidu.com/s?id=1583441733083989684&wfr=spider&for=pc

http://blog.csdn.net/cy609329119/article/details/51771953

https://blog.csdn.net/xiaomingdetianxia/article/details/77446762

相关文章
相关标签/搜索