jvm垃圾回收(gc)算法、收集器比较总结

判断对象是否可回收(是否存活)

1、引用计数法:

记录引用次数,不被引用减一,缺点,无法解决循环嵌套引用(hotspot不适用)

gc信息的打印 -verbose:gc (打印简单) -XX:+PrintGCDetails(打印详细)

2、可达性分析法

根据 GcRoot 是否可以达到对应对象来判断。可以解决嵌套问题

GcRoots :虚拟机栈,方法区类属性(静态)引用对象,方法区常量引用对象。本地方法栈

 

清除算法

1、标记-清除法

1.1 效率较低,标记清除执行效率不高

1.2 空间问题,空间不规整,大数据无法存储

2、复制算法-针对新生代

2.1 内存空间分布为两部分,使用标记清除后,将存活内容移动到另一个区域整合。然后在新的区域写入,再整合。问题是浪费内存

2.2 hotspot 分年代算法

新生代:eden,survivor1,survivor2

老年代: tenured Gen

2.3

1.eden 放入新对象,判断存活放入survivor(eden不足会触发垃圾回收)

2.清理无用,放入另一个survivor。

3.再次存入,清理eden和survivor,然后放入另一个survivor

(一般分配,eden 80%,survivor 10%*2,当survivor不足放入老年代)

 

3、标记整理算法-老年代

将内存局域分割两部分,每次进行标记,标记之后再进行移动,一遍清理,一遍不清理,比标记清理算法性能高

 

4、分代算法

将内存分代,新生代和老年代分别采用复制算法和标记整理算法不同的算法

 

垃圾收集器(垃圾回收时代码暂停)

1、serial收集器(复制算法)并行-新生代

最基本,发展最悠久的。单线程的收集。回收效率低。但是适用于桌面应用等占用内存小的。单线程效果好

2、parnnew(复制算法)并行-新生代

多线程收集器,将单线程回收变为多线程并发收集(复用了大部分serial代码)

关注点在于减少收集时间

优点 cms 回收老年代,只能配合serial和parnnew 无法配合 parallel

3、parallel(复制算法)并行-新生代

和parnnew类似,多线程收集器

区别关注点不同:

parallel关注点在于 控制吞吐量(cpu执行用户代码时间与cpu总耗时比值)总耗时位 代码时间+垃圾回收时间

两个参数控制,1、垃圾回收的最大时间(-XX:MAXGCPauseMillis) 2、指定吞吐量(0-100之间)-XX:GCTimeRatio

parnnew 关注点在于 降低每次垃圾回收的时间

4、cms Concurrent Mark Sweep(标记清除算法,一般针对老年代)

并发收集:

1、初始标记(对GCRoots直接关联对象进行标记)

2、根据初始标记进行并发标记

3、对并发标记中产生的垃圾进行并行标记

4、并发清理标记垃圾

优点:

1、并发收集

2、低停顿(但是吞吐量不高,并发吞吐量低于并行)

缺点:

1、cpu占用高(所有多线程缺点)

2、产生浮动垃圾,执行第4步骤时候产生的垃圾

3、空间碎片(算法缺陷)

4、Concurrent Mode Failure (要在内存区域中制定一块在并发标记和清理过程使用,过大浪费过小就会出现这个异常,当出现这个异常时就会采用serial-old版本(单线程并行,标记整理算法),更加浪费时间)

5、G1(标记整理算法)新生代+老年代

收集:收集流程和cms类似(除了初始标记以外,都可以使用并发或者并行),最终为筛选回收

优点:

1、并行与并发

2、分代收集

(将内存区域分为很多region,存在rememberSet表对 region分类排序(E S O H 其中h用来借贷给其他region存储巨型对象,可以使用多个合并),对收集效率更高的模块进行收集)

在写入过程中,会有一个写入中断进行判断,是否和引用是同一个region,如果不是同一个,就会把引用记录rememberSet中,也会将rememberSet作为GCRoots进行可达性分析(进其他分代算法中,如果两个不同代引用,单独代回收没法回收,只能通过full Gc进行收集)

3、空间整合(算法优势)

4、可预测停顿(可以指定在一个长度m毫秒时间,垃圾收集时间不超过n毫秒)

与cms相比较,优势可预测(减少)停顿,单说吞吐量并不比cms高多少,适用于很大的应用,动则几百G的内存占用,分布式的建构回收使用cms足够了

 

你可能感兴趣的:(虚拟机,垃圾回收,虚拟机,垃圾回收算法,gc)