美文网首页JVM
JVM07 JVM是如何回收垃圾的?

JVM07 JVM是如何回收垃圾的?

作者: 夜阑人儿未静 | 来源:发表于2019-01-03 15:37 被阅读33次

    免费的其实是最贵的,Java 虚拟机自带自动机制的内存管理、垃圾回收,但这种自动机制会带来不少与垃圾回收实现相关的问题。所以作为java开发了解Jvm的垃圾回收还是很有必要的。

    哪些对象可以被回收?

    1.引用计数器算法(JDK1.2)

    即当这个类被加载到内存以后,就会产生方法区,堆栈、程序计数器等一系列信息,当创建对象的时候,为这个对象在堆栈空间中分配对象,同时会产生一个引用计数器,同时引用计数器+1,当有新的引用的时候,引用计数器继续+1,而当其中一个引用销毁的时候,引用计数器-1,当引用计数器被减为零的时候,标志着这个对象已经没有引用了,可以回收了!
    缺点:需要额外的空间来存储计数器,繁琐的更新操作,无法处理循环引用对象

    2.根搜索算法(可达性分析算法)

    设立若干种根对象,当任何一个根对象到某一个对象均不可达时,则认为这个对象是可以被回收的可以理解为由堆外指向堆内的引用。哪些能当做GC roots呢?
    虚拟机栈中的引用的对象。
    方法区中的类静态属性引用的对象。
    方法区中的常量引用的对象。
    本地方法栈中JNI的引用的对象。
    Stop-the-world:停止其他非垃圾回收线程的工作,直到完成垃圾回收,会造成暂停时间。

    什么时候回收?

    到这里要先了解一个概念:GC分为minor GC 和 Full GC(major GC)。Java堆内存分为新生代和老年代,新生代中又分为1个eden区和两个Survior区域(from-to)。
    新创建的对象都会被分配到eden区,这些对象经过一个minor gc后仍然存活将会被移动到Survior区域中,对象在Survior中每熬过一个Minor GC,年龄就会增加一岁,当他的年龄到达一定程度时(15),就会被移动到老年代中。

    1.执行 system.gc()的时候
    2.当Eden中没有足够空间时,虚拟机将发生一次Minor GC。Minor GC非常频繁,而且速度也很快
    3.当老年代没有足够的空间时即发生Full GC,发生Full GC一般都会有一次Minor GC,为了减少老年代的全堆空间扫描,引入卡表技术,大致地标出可能存在老年代到新生代引用的内存区域。
    4.发生Minor GC时,虚拟机会检测之前每次晋升到老年代的平均大小是否大于老年代的剩余空间大小,如果大于,则进行一次Full GC,如果小于,则查看HandlePromotionFailure设置是否允许担保失败,如果允许,那只会进行一次Minor GC,如果不允许,则改为进行一次Full GC。
    如何回收?
    1.清除

    把死亡对象所占据的内存标记为空闲内存并记录在一个空闲列表(free list)中。当需要新建对象时,内存管理模块便会从该空闲列表中寻找空闲内存,并划分给新建的对象。
    缺点:会造成内存碎片,分配效率较低。

    2.压缩

    把存活的对象聚集到内存区域的起始位置从而留下一段连续的内存空间。
    缺点:虽然解决了内存碎片化的问题,但代价是压缩算法的性能开销。

    3.复制

    把内存区域分为两等分,分别用两个指针 from 和 to 来维护,并且只是用 from 指针指向的内存区域来分配内存。当发生垃圾回收时,便把存活的对象复制到 to 指针指向的内存区域中,并且交换 from 指针和 to 指针的内容。
    缺点:堆空间的使用效率极其低下。
    以上三种都有缺点,垃圾回收器往往会综合上述几种回收方式,综合它们优点的同时规避它们的缺点。

    jvm的垃圾收集器用的是什么?

    针对新生代的垃圾回收器共有三个:Serial,Parallel Scavenge 和 Parallel New。这三个采用的都是标记 - 复制算法
    Serial :单线程
    Parallel New:可以看成 Serial 的多线程版本
    Parallel Scavenge:和 Parallel New 类似,但更加注重吞吐率,不能与 CMS 一起使用

    针对老年代的垃圾回收器也有三个:Serial Old 和 Parallel Old,以及 CMS。Serial Old 和 Parallel Old 都是标记 - 压缩算法
    Serial Old :单线程
    Parallel Old:Serial Old 的多线程版本
    CMS:采用的是标记 - 清除算法,并且是并发的,Java 9 中已被废弃

    G1(Garbage First)是一个横跨新生代和老年代的垃圾回收器。实际上,它已经打乱了前面所说的堆结构,直接将堆分成极其多个区域。每个区域都可以充当 Eden 区、Survivor 区或者老年代中的一个。它采用的是标记 - 压缩算法,而且和 CMS 一样都能够在应用程序运行过程中并发地进行垃圾回收。
    G1 能够针对每个细分的区域来进行垃圾回收。在选择进行垃圾回收的区域时,它会优先回收死亡对象较多的区域。

    ZGC:Java 11 新加入的,号称可以达到10ms 以下的 GC 停顿.

    相关文章

      网友评论

        本文标题:JVM07 JVM是如何回收垃圾的?

        本文链接:https://www.haomeiwen.com/subject/jlofrqtx.html