3.2对象死亡的判断方法
3.2.1引用计数法
给对象添加一个引用计数器,每当一个地方引用它就+1,引用失效就-1,当计数器为0时就表示对象已经死亡。
缺点是无法解决循环引用问题
3.2.2可达性分析
将GC root作为根节点向下遍历,无法遍历到的对象(GC Root到这个对象不可达)就表示该对象已经死亡。
3.2.3对象的自救
已经死亡的对象会被第一次标记,然后进行筛选,筛选出是否有必要执行finalize()方法,如果对象有并且是第一次被调用那么对像将被放在F-Queue队列中,等待虚拟机触发这个方法,如果在finalize()方法中与任何一个对象建立关联则该对象还可以存活
3.2.4回收方法区
永久代的回收(full GCf)主要内容是:废弃常量和无用的类
常量的回收:和堆中的对象相似,当系统中没有String对象引用时会被回收。
无用的类必须满足三个条件:
该类的所有实列已经被回收
1. 加载该类的classloader已经被回收
2. 该类对应的java.lang.Class对象没有被任何地方引用,无法通过反射访问该类
3.3垃圾回收算法
3.3.1标记-清楚算法
先将所有可回收对像进行标记然后再回收
缺点是效率低,产生的碎片多
3.3.2复制算法
将存活的对象复制到另一半内存中,当另一半内存不够时会向永久代进行分配担保
将堆分为了Eden From Survivor, To Survivor 默认比列是8:1:1
3.3.3分代收集算法
新生代使用复制算法 老年代使用标记清理或标记整理
3.4垃圾收集器
Serial: 最基本最悠久的,单线程,工作时会stop the world 简单而高效
ParNew: Serial的多线程版本
Parallel Scavenge:可以控制吞吐量,和最大垃圾收集停顿时间。动态调节新生代的大小,Eden与Survivor的比列,晋升老年代对象的大小等细节参数提供最合适的停顿时间或者最大吞吐量
Serial Old:serial的老年代版本
Parallel Old:Parallel的老年代版本
CMS: 工作分为四个步骤 初始标记 并发标记 重新标记 并发清除
CMS收集器对CPU资源敏感
CMS收集器无法处理浮动的垃圾
CMS会产生很多碎片
G1:是目前的最新成果,它并行与并发 分代收集 空间整合 可预测的提顿 将java堆分为多个Region
工作步骤:初始标记,并发标记 最终标记 筛选回收
3.5内存分配与回收策略
- 对象优先在Eden分配
- 大对象直接进入老年代
- 长期存活的对象进入老年代也就是对象的年龄>=MaxTenuringThreshold设定的年龄
- 动态对象年龄:满足同年对象达到Survivor空间的一半