目录
4.3Parallel Scavenge收集器(新生代,可控制吞吐量)
1确定对象是否死亡
1.1引用计数法
给对象添加一个引用计数器,被引用时+1,引用失效-1,为0时确定对象不再被使用
缺点:
很难解决循环引用
1.2可达性分析算法
1.3再谈引用
1.4对象死亡过程与拯救
对象死亡需要经历两次标记过程:
- 第一次标记:
对象经过可达性分析后发现没有与GC Roots相连接的引用链,会被第一次标记和筛选。
筛选条件:对象覆盖了finalize()方法且finalize()方法未被虚拟机调用
经过筛选后会被放置在F-Queue队列,并在稍后被Finalizer线程执行。
- 第二次标记:
如果对象在finalize()方法中拯救自己(重新与引用链上的任何一个对象建立关联),第二次标记时将被移除,否则面临被回收。
实际中避免finalize()方法使用。
1.5回收方法区
Java虚拟机规范不要求在方法区实现垃圾收集。
2垃圾收集算法
2.1标记-清除算法
- 不足:
标记和清除效率都不高
内存碎片
2.2复制算法(新生代)
每次用一半
- 缺点:
在对象存活率高时要进行较多复制操作,效率变低
需要担保
老年代不采用这种算法
2.3标记整理算法(老年代)
先移动,再清理
3HotSpot的算法实现
3.1枚举根节点
可达性分析会消耗很多时间
且要在一致性的快照中进行,导致GC进行时必须停顿所有Java执行线程
3.2安全点
程序执行至Safepoint(安全点)才能暂停执行GC
Safepoint以“让程序长时间执行”为标准选定,例如方法调用、循环跳转、异常跳转
抢占式中断:GC发生时中断所有线程,若线程不在安全点恢复,使其继续运行至安全点
主动中断:设置标志,线程主动轮询
3.3安全区域
程序不执行时(未分配CPU时间,sleep或blocked),无法执行至安全点
4垃圾收集器
4.1Serial收集器(新生代单线程)
单线程,且要暂停工作线程
用于client模式
4.2ParNew收集器(新生代并行)
多线程版本Serial收集器
能与CMS配合
4.3Parallel Scavenge收集器(新生代,可控制吞吐量)
与ParNew区别:
关注点不同。其他收集器关注缩短用户线程停顿时间(提高响应速度,用于与用户交互的程序),Parallel Scavenge关注吞吐量(尽快运算完,适合后台)
4.4Serial Old收集器(单线程老年代)
4.5Parallel Old收集器(并行老年代)
4.6CMS收集器(并发标记清除,老年代,低停顿)
Concurrent Mark Sweep
注重回收停顿,用于B/S系统服务端
优点:并发,低停顿
4.6.1三个明显缺点:
老年代需要预留空间保存用户线程产生的浮动垃圾
标记清除算法产生的碎片,内存整理无法并发执行
4.7G1收集器
4.8理解GC日志
-XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:./gclogs
参考https://blog.csdn.net/yxc135/article/details/12137663
4.9垃圾收集器参数总结
5内存分配回收策略
5.1对象优先在Eden分配
5.2大对象
5.3长期存活的对象进入老年代
5.4动态对象年龄判定
5.5空间分配担保
在发生Minor GC之前,虚拟机会检测 : 老年代最大可用的连续空间>新生代所有对象总空间?
满足,Minor GC是安全的,可以进行Minor GC。
不满足,虚拟机查看HandlePromotionFailure参数:
(1)为true,允许担保失败,会继续检测老年代最大可用的连续空间>历次晋升到老年代对象的平均大小。
若大于,将尝试进行一次minor gc。若小于,则重新进行一次full gc。
(2)为false,则不允许冒险,要进行full gc(对老年代进行gc)。