JVM学习笔记2:Java垃圾回收

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角色互换。

图示:
回收前:



回收后:



扫描二维码关注公众号,回复: 3583047 查看本文章

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垃圾回收机制

猜你喜欢

转载自www.cnblogs.com/Zafkiel/p/9788682.html