JVM学习笔记2:Java垃圾回收
学习JVM,Java虚拟机对理解Java程序执行过程和Java程序性能调优具有很大帮助。本系列博客旨在由浅到深学习并理解JVM。参考阅读:《深入理解Java虚拟机-JVM高级特性和最佳实践》。这个书写的非常好,推荐有条件的读者买一本来阅读,网上也有电子版的。本系列基于HotSpot虚拟机。
欢迎转载,转载请注明出处;笔者水平有限,错误之处欢迎指正!
本篇是系列的第2篇。
一、垃圾回收机制的意义
先简单回顾下JVM内存模型:虚拟机栈、本地方法栈、程序计数器。(线程私有)
java堆、方法区。(线程共享)
Java垃圾回收可以分为三个问题:
①哪些内存需要回收:判断对象是否可以被回收的两种算法。引用计数法和可达性分析算法。
②什么时候回收:堆的新生代、老年代、永久代(已被移除),MinorGC和FullGC。
MinorGC:新生代Eden区满(非必要条件),触发MinorGC,回收新生代。FullGC,老年代满了,触发FullGC,回收新生代和老年代。
③如何回收:三种经典垃圾回收算法(标记清除算法、复制算法、标记整理算法)和分代收集算法以及七种垃圾收集器。
Stop-the-World:JVM执行GC时停止应用程序的执行。GC优化目标:减少stop-the-world发生的时间,使得系统具有高吞吐、低停顿的特点。
二、如何判断对象是否可以被回收
1.引用计数算法:判断对象的引用数量
通过判断对象的引用计数数量来决定是否可以被回收。对象被创建,对象分配给一个引用变量,该对
象的引用计数设为1.其他引用变量赋值这个对象的引用,对象的引用计数加1;该对象的某个引用超过生命
周期或者设置为一个新值,对象的引用计数减1。任何引用计数为0的对象可以当做垃圾回收。
相互循环引用,无法被回收。
如下实例:
/**
* @author Zafkiel
*/
public class ReferenceCountingGC {
public Object instance=null;
public static void testGC(){
ReferenceCountingGC objA=new ReferenceCountingGC();
ReferenceCountingGC objB=new ReferenceCountingGC();
objA.instance=objB;
objB.instance=objA;
objA=null;
objB=null;
System.gc();
}
}
2.可达性分析算法:判断对象的引用链是否可达
通过判断对象的引用链是否可以可达来决定对象是否可以被回收。
图论:从“GC Roots”为起点,向下搜索,GC Roots到这个对象不可达。
GC Roots可以为:
①虚拟机栈(栈帧的局部变量表)中引用的对象
②方法区中类静态属性引用的对象。
③方法区中常量引用的对象。
④本地方法栈Native方法引用的对象。
图示:
三、垃圾收集算法
1.标记-清除算法
标记-清除算法分为标记和清除两个阶段。
标记处全部要回收的对象,标记完成后统一回收所有标记对象。
缺点:①,效率不高;②会产生大量不连续内存碎片无法分配大对象。
图示:
回收前:
回收后:
2.复制算法
复制算法:将内存分成大小相等两块(A和B),A块使用完将A块存活对象复制到B块,把使用过的A块全部清理。
优缺点:优点,简单高效;缺点,可用内存减半。
实践:新生代垃圾回收。新手代对象大多数生命期短,新生代中Eden:Survivor:Survivor=8:1:1,每次使用Eden和SurvivorA,回收则将存活对象复制到SurvivorB后清除Eden和SurvivorA,而后SurvivorA和SurvivorB角色互换。
图示:
回收前:
回收后:
3.标记-整理算法
标记-整理算法与标记-清理算法算法一样,先标记所有要回收对象,然后将存活对象向一端移动,再清理边界外内存。
图示:
回收前:
回收后:
四、垃圾收集器
新生代使用复制算法,老年代使用标记-整理算法。七种垃圾收集器如下图所示:
1.Serial收集器
Serial收集器:单线程,简单高效。
2.ParNew收集器:
ParNew收集器:Serial收集器的多线程版本。
3.Parallel Scavenge收集器:
新生代多线程收集器,旨在减小用户线程停顿时间、提高吞吐量。
4.Serial Old收集器
Serial Old是Serial的老年代版本,单线程,使用标记-整理算法。
5.Parallel Old收集器
Parallel Old是Parallel Scavenge的老年版本,多线程,使用标记-整理算法。
6.CMS收集器
旨在获取最短回收停顿时间,在互联网站和B/S系统的服务端较适用。它使用标记-清除算法,可分为四步:①初始标记;②并发标记;③重新标记;④并发清除。优点是并发收集、低停顿。
7.G1收集器
面向服务端应用,优点是:①并行和并发:充分利用多CPU多核环境减少停顿时间;②分代收集:③空间整合,不会产生内存碎片,提供规整内存;④可预测的停顿:建立可预测停顿时间模型。
这里简单介绍了七种垃圾收集器,有兴趣的读者可以去参阅其他文档。
简单总结:
1.判断对象是否可被回收:引用计数算法和可达性分析算法。
2.垃圾收集算法:①标记-清除算法;②复制算法;③标记-整理算法
3.七种垃圾收集器:
新生代:Serial收集器、ParNew收集器、Parallel Scavenge收集器;
老年代:Serial Old收集器、Parallel Old收集器、CMS收集器;
新生代和老年代:G1收集器。
引用:
《深入理解Java虚拟机》(周志明)
图解Java垃圾回收机制