一.引言
java堆Heap分为新生代和老年代两个部分,垃圾回收算法主要是针对这两个内存区。
1.可达性分析
从GC Root开始递归搜索其引用的对象,如果一个对象不在这个引用链上,那么这个对象就是不可达的,便应该被回收。
可以作为GC Root的对象:
- 方法区中的类静态属性引用的对象——存放在运行时常量池;
- 方法区中常量引用的对象——final修饰的属性;
- 虚拟机栈的栈帧中的本地变量表中引用的对象——虚拟机栈为线程独有。
2. CMS适用场景
CMS(concurrent mark sweep)是为那些喜欢喜欢比较短的垃圾回收暂停时间,并且愿意在运行期间与垃圾回收器共享cup资源的应用。
典型的,如果一个应用运行在多核处理器上,并且其老年代拥有比较多的长期存活的数据,那么比较适合使用CMS。CMS可以使用参数XX:+UseConcMarkSweepGC
开启。
3. 过多的GC时间和内存溢出
CMS会抛出OutOfMemoryError
,如果太多时间消耗在垃圾回收上:如果超过98%的时间消耗在垃圾回收上,而且不到2%的堆内存被回收,那么OutOfMemoryError
就会被抛出。
这种特性旨在用来保护应用程序长时间运行,同时由于堆内存太小而导致垃圾回收没什么进展。如果需要,这个特性可以使用参数来禁止:-XX:UseGCOverheadLimit
。
二. CMS执行周期
CMS执行周期分为6个阶段,分别是:1.初始标记->2.并发标记->3.并发预清理->4.重新标记->5.并发清理->6.重置
。其中1、4初始标记和重新标记阶段都需要暂停所有用户线程。
2.1 初始标记
此阶段暂停所有用户线程,并且标记与GC Root直接关联的对象。
2.2 并发标记
该阶段进行GC Root tracing:初始标记阶段所有暂停的线程开始运行;从此前标记过的对象出发,标记与GC Root间接关联的对象。
2.3 并发预清理
此阶段用于标记从新生代晋升到老年代的对象、新分配到老年代的大对象和并发标记阶段被修改过的对象。
2.4 重新标记
暂停所有应用线程,重新扫描堆中的对象(新生代、老年代),进行可达性分析,标记对象。此阶段是多线程的,而且有了前边的基础,所以会很快。
2.5 并发清理
此阶段清理无效的对象。
2.6 重置
CMS清除内部状态,为下次回收做准备。