博文转自:http://www.blogjava.net/showsun/archive/2011/07/21/354745.html
1、引用计数(reference counting)
原理:此对象有一个引用,则+1;删除一个引用,则-1。只用收集计数为0的对象。
2、复制(copying)
原理:把内存空间划分为2个相等的区域,每次只使用一个区域。垃圾回收时,遍历当前使用区域,把正在使用的对象复制到另外一个区域。
优点:不会出现碎片问题。
缺点:1、暂停整个应用。2、需要2倍的内存空间。
原理:把内存空间划分为2个相等的区域,每次只使用一个区域。垃圾回收时,遍历当前使用区域,把正在使用的对象复制到另外一个区域。
优点:不会出现碎片问题。
缺点:1、暂停整个应用。2、需要2倍的内存空间。
3、
原理:对于“活”的对象,一定可以追溯到其存活在堆栈、静态存储区之中的引用。这个引用链条可能会穿过数个对象层次。第一阶段:从GC roots开始遍历所有的引用,对有活的对象进行标记。第二阶段:对堆进行遍历,把未标记的对象进行清除。这个解决了循环引用的问题。
缺点:1、暂停整个应用;2、会产生内存碎片。
4、
原理:第一阶段标记活的对象,第二阶段把为标记的对象压缩到堆的其中一块,按顺序放。
优点:1、避免标记扫描的碎片问题;2、避免停止复制的空间问题。
5、分代(generational collecting)
原理:基于对象生命周期分析得出的垃圾回收算法。把对象分为年轻代、年老代、持久代,对不同的生命周期使用不同的算法(2-3方法中的一个即4自适应)进行回收。
如上图所示:为Java的各代分布图
年轻代(young)
分为3个区。一个Eden区,2个survivor区。大部分对象在Eden中生成。当Eden区满时,还存活的对象将被复制到survivor区。当该survivor区满时,此区的存活对象被复制到另外一个survivor区,当第2个survivor区也满时,该区还存活的对象将被复制到年老区(tenured)。
年老代(tenured)
存放从年轻代(young)复制过来的对象。
持久代(perm)
用于存放静态文件,如Java类、方法等。持久代对垃圾回收没有显著的影响,但是有些应用可能动态生成或者调用一些class。 持久代大小通过
Thinking in java给java gc取了一个罗嗦的称呼:“自适应、分代的、停止-复制、标记-扫描”式的垃圾回收器。
导致Gc的情况:
1、tenured被写满
2、perm被写满
3、System.gc()的显式调用。
4、上一次GC之后heap的各域分配策略动态变化。