GC判断对象是否存活算法
1> 引用计数算法
2> 根搜索算法(GC Root)
GC垃圾收集算法
1> 标记清除算法(Mark-Sweep):分为标记和清除两个阶段,首先标记出可以回收的对象,标记完后统一回收。缺点如下:
a) 效率低:标记和清除过程效率都不高;
b) 空间问题:清除之后产生大量不连续的内存碎片。
2> 复制算法(Copying):将内存划分成大小相等的两块,每次只使用其中的一块,当需要清理时,就直接将存活的对象复制到另一块。这种方式实现简单效率高,也不会存在碎片问题,缺点:实际可用内存缩小为原来的一半。
3> 标记整理算法(Mark-Compact):与标记清除相似,不相点在于整理对将存活的对象向一端进行移动,不会产生碎片。
4> 分代收集算法(Generational Collection):根据存活周期的不同将内存划分为几块。
JVM虚拟机GC回收算法
1> 分代收集:分为年青代和老年代
2> 复制收集:年青代使用了2个幸存区来实现复制(默认比例:8:1:1,其中1用于交换,因此实际可用为90%)
3> 标记整理:老年代由于对象的存活率高,所以适合使用标记整理或标记清除来进行回收
JVM垃圾收集器
1> 年青代(Young Generation):Serial、PartNew、Parallel Scavenge -> G1
2> 老年代(Tenured Generation):CMS、Serial Old(MSC)、Parallel Old -> G1
Serial:Jdk1.3.1之前版本,特点是单线程收集,Stop the world
PartNew:Serial的多线程版,Stop the world
Parallel Scavenge:与PartNew相似,也是多线程收集,区别在于可以通过参数来控制吞吐量(即gc的停顿时间及gc时间比例)
Serial Old:单线程收集,使用标记整理算法
Parallel Old:Parallel Scavenge的老年代版本,使用多线程及标记整理算法
Concurrent Mark Sweep(CMS):以最短GC停顿时间为目标的收集器,可以通过参数来控制对碎片的压缩(是否开启压缩开关及压缩的频率设置)
G1(Garbage First):G1对新生代及老年代同时进行管理,划分成多固定大小的独立区域Region,采用标记整理算法,实现不牺牲吞吐量的前提下进行低停顿的回收
MinorGC及FullGC
1> 新生代GC(Minor GC):指发生在新生代的垃圾回收,一般是对生命周期较短的对象的回收(例如:方法内部声明对象),通过幸存区交换来处理所以回收速度快
a) 触发条件:当创建对象时Eden区空间不够时触发,当执行Minor GC时单个对象大于幸存区时,通过分配担保机制转移动老年代。
b) 推荐:由于Minor GC速度快,建议及时将不使用的对象置空,利于对象在新生代回收;
不建议创建生命周期短的大对象造成频繁的GC,
可以通过参数设置阀值将大对象直接进老年代
(默认在幸存区交换15次会移至老年代;动态年龄判断:幸存区中同龄所有对象大于幸存区空间的一半,年龄大于等于该年龄的对象可以直接进入老年代)。
2> 老年代GC(Full GC/Major GC):指发生在老年代的垃圾回收,标记整理回收速度慢(比MinorGC慢10倍以上)并且会有暂停响应(stop the world)。
如果FullGC非常频繁(90%以上时)将会严重影响服务性能,此时就需要调整堆内存参数大小或将大对象转至堆外存。
示例:
/usr/local/java/bin/jstat -gccause 16463 1000 # 查看gc变化情况(16463为进程ID,1000表示每1000毫秒更新一次结果)
GC回收永久代的条件
1> 该类所有的实例都已经被回收,即堆中不存在该类的任何实例;
2> 该类的ClassLoader已经被回收;
3> 该类的Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。