新生代的垃圾回收(minor gc)
当新生代满了,执行的垃圾回收就是minor gc。
- 绝大部分新创建的对象在eden区。
- 当eden区满了, Minor GC 就执行,而且所有的survivor区域里面的对象,丢到一个survivor里面。
- 在一个时间中,必定其中一个survivor区是空的。
- 好多轮minor GC后还是存在的对象,会被移到老生代。一般是有一个门限(threshold for the age of the young generation )
老生代的垃圾回收(major gc)
老生代满了就执行这个gc
perm只在full gc下执行垃圾回收(目前发现只有cms会回收p区?)
执行上述的垃圾回收,都会暂停jvm里面的所有应用!
minor gc是很快的,但是major gc很耗时。
full gc就是分别执行minor gc,major gc,还垃圾回收了p区。
垃圾回收算法
1、标记--清除算法(mark-sweep)
最基本、最早的垃圾回收算法。一般是不适用的。
比如说某个generation内存耗尽时触发。
步骤如下:
--stop the world。
--遍历所有gc roots。可达到的表示为存活。
--遍历heap中的对象,将没有标记为存活的清除。
缺点:慢,需要遍历;清理出来的空间不是连续的。
(参考:http://www.th7.cn/Program/java/201308/146907.shtml)
2、复制(copying)
常用的实现算法。
把一个区域中存活的复制到另外一个区域中。
比如说eden+一个survivor——>另外一个survivor。
也满了的话,丢到老生代。
缺点:对象存活率较高,就会变慢。
3、标记--整理(mark-compact)
老年代的实现方式。
--stop the world。
--遍历所有gc roots。可达到的表示为存活。
--所有存活的对象向一边移。
4、分代收集(generational collection)
当前的商用收集方法。
是2、3的综合体。根据对象特征, 使用2还是使用3。
垃圾收集器
无论哪一种垃圾收集器, 都会stop the world。只是停顿时间长短区别。
不同的垃圾收集器有不同的作用。
serial收集器:
最早的实现。
单线程。
用于新生代。
使用复制算法。
还在使用,运行在client模式下的虚拟机是不错的。
Parallel Scavenge:
多线程,用于新生代。
使用复制算法。
可以用于server模式。
不建议单CPU下使用。
ParNew收集器:
增强版Parallel Scavenge,可以与CMS配合使用。
Serial old:
单线程。
标记--清除算法。
用于老生代
Parallel Old:
多线程
标记-整理算法。
用于老生代
CMS:
多线程, 用于老生代。
两次stop the world。
cms一般是sweep(清除)操作,而不是。整理后空间是不连续的。
有一个阀值,空间不连续到一定程度后compact(整理)。或者进行full gc。
有一个参数设置,可以收集p区。
- 初始标记(init mark):收集根引用,这是一个stop-the-world阶段。
- 并发标记(concurrent mark):这个阶段可以和用户应用并发进行。遍历老年代的对象图,标记出活着的对象。
- 并发预清理(concurrent preclean):这同样是一个并发的阶段。主要的用途也是用来标记,用来标记那些在前面标记之后,发生变化的引用。主要是为了缩短remark阶段的stop-the-world的时间。
- 重新标记(remark):这是一个stop-the-world的操作。暂停各个应用,统计那些在发生变化的标记。
- 并发清理(concurrent sweep):并发扫描整个老年代,回收一些在对象图中不可达对象所占用的空间。
- 并发重置(concurrent reset):重置某些数据结果,以备下一个回收周期开始。
|
G1:
不区分新生代还是老生代的垃圾收集器。基于标记--整理。没有碎片。
不同的垃圾回收器,作用在何处:
参考:
有道云笔记:http://note.youdao.com/share/?id=4e102baa9a3fa30230ff3837f6a9e79e&type=note