什么对象需要被回收??
没有被引用的对象要被回收。
怎么判定对象已经没有被引用???
1、引用计数算法。(因为循环引用问题,java没有使用这种方法)
2、可达性分析法。
主流实现。判定对象是否被引用。从GC ROOTS节点找引用链。
(对象的引用有分为:强引用、软引用、弱引用、虚引用。 先不管~)
根据区域划分垃圾回收
新生代的垃圾回收(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区。
|
G1:
不区分新生代还是老生代的垃圾收集器。基于标记--整理。没有碎片。
不同的垃圾回收器,作用在何处:
参考:
https://blogs.oracle.com/jonthecollector/entry/our_collectors
cms垃圾采集器:http://blog.griddynamics.com/2011/06/understanding-gc-pauses-in-jvm-hotspots_02.html
有道云笔记:http://note.youdao.com/share/?id=4e102baa9a3fa30230ff3837f6a9e79e&type=note