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足够了