说到JVM垃圾回收,我们通常会问三个问题,回收对象是什么?什么时候回收?怎么回收?JVM垃圾回收主要回收的区域是Java堆,通过了解JVM内存结构,我们知道堆主要负责对象和数组的存储。堆还可以进行细分。
一、堆内存分类
1. 新生代 - 新对象进入新生代,新生代可以分为三个区域
eden -新对象首先进入的区域
from survior -新生代另外一个区域
to survior -同上
2. 老年代old generation -- 在新生代中经历了N次垃圾回收后仍然存活的对象就会被放到老年代中。而且大对象直接进入老年代。
new出来的对象进入eden区。因为大部分对象都是朝生夕死,根据经验分析,一般eden和survior的大小比为8:1。当eden满了则进行一次minor GC,如果对象大小大于survior区大小则对象进入老年区。为什么需要分代,因为如果不分的话对所有对象进行标记-清理的话,则效率较低,而且清理会使虚拟机暂停,影响性能。为什么要有2个survior区,这是为了减少碎片的产生。当进行一次minorGC时,如果只有一个survior区,那么会导致碎片产生。如果有2个survior的话,eden和一个survior的存活的对象一起复制到另外一个survior区,则没有碎片
二、什么时候回收
当堆内存不足时进行回收,这里回收方式有2种
1. minor gc --新生代GC回收,速度快,频率高
2. full gc触发 --老年代GC回收,速度慢比minorGC慢10倍左右,频率低
三、回收对象
1. 引用计数算法
基本原理:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1。任何时刻计数器为0的对象就是不可能再被使用的
优点:简单,高效
缺点: 很难处理循环引用
2. 可达性分析算法
基本原理:从GC Roots(每种具体实现对GC Roots有不同的定义)作为起点,向下搜索它们引用的对象,可以生成一棵引用树,树的节点视为可达对象,反之视为不可达
如何判断对象已死
四、如何回收
1. 回收算法
1. 标记清除算法 (Mark-Sweep)
基本原理:从根节点开始,标记出所有可达的对象;然后清除所有未标记的对象
缺点:效率低,需要从头到尾遍历;产生较多不连续的碎片
2. 复制算法 (Copying)
基本原理:从根节点开始,标记出所有可达的对象;然后清除所有未标记的对象
优点:效率高,不用考虑碎片等复杂情况
缺点:只能用一半内存
3. 标记整理算法 (Mark-Compact)
基本原理:从根节点开始,标记出所有可达的对象;然后让所有对象向一端移动,然后清理掉边界以外的内存
优点:不会产生内存碎片
缺点:在标记的基础之上还需要进行对象的移动,成本相对较高,效率也不高
4. 分代回收算法
2. 回收器
新生代回收器
Serial 单线程:简单高效
ParNew Serial的多线程版本,能与CMS配合,不能与PS配合
Parallel Scavenge 复制算法,多线程并行,适合对响应时间要求较高的场景
老年代回收器
Serial Old 单线程,搭配PS
Parallel Old PS的老年版
CMS 获取最短时间为目标的收集器
G1 基于标记整理,能非常精确的控制java堆
《Java Garbage Collection Basics》
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
《Java虚拟机详解----JVM常见问题总结》
http://www.cnblogs.com/smyhvae/p/4810168.html