jvm(2)垃圾回收

xiaoxiao2021-02-28  8

一.如何判断对象为垃圾对象?

    1.引用计数法

        在对象中添加引用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,当引用失效的时候,计数器的值就-1

        (1)idea中打印GC日志的方法:    

                 添加:-XX:+PrintGCDetails

        (2)没有虚拟机采用这种算法回收垃圾,因为出现对象之间互相引用的时候,即使栈中的引用不指向该对象了,引用计数器的值仍不为0

    2.可达性分析法

    (1)可作为GCRoot:虚拟机栈    方法区中类属性,常量引用的对象   本地方法栈引用的对象

    (2)从GCRoot节点向下搜索,当某个对象对GCRoot节点没有任何引用链相连接,就可以被垃圾回收器回收

二.如何回收

    1.回收策略

    (1)标记-清除算法

            标记:标记的过程其实就是遍历所有的GC Roots,然后将所有的GC Roots可达的对象标记为存活的对象

            清除:清除的过程将遍历堆中所有的对象,然后将没有标记的对象全部清除掉

            带来的问题:效率问题和空间问题-->造成内存区块不连续,当有大的对象需要开辟内存,可能找不到一块足够大的连续的内存空间,然后会再次调用垃圾回收器进行回收,影响效率

    (2)复制算法

            就是为了解决标记-清除算法产生的碎片

            jvm将堆分为新生代和老年代,又将新生代划分为Eden(伊甸园)和两块survivor space(幸存者区)

            算法流程

            1、当Eden区满的时候,会触发第一次young gc,把还活着的对象拷贝到Survivor From区(如过存不下,触发老年代的分配担保,直接将对象存到老年代);当Eden区再次触发young gc的时候,会扫描Eden区和From区域,对两个区域进行垃圾回收,经过这次回收后还存活的对象,则直接复制到To区域,并将Eden和From区域清空。             2、当后续Eden又发生young gc的时候,会对Eden和To区域进行垃圾回收,存活的对象复制到From区域,并将Eden和To区域清空。             3、可见部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认是15),最终如果还是存活,就存入到老年代

    (3)标记-整理算法

            

            标记:它的第一个阶段与标记/清除算法是一模一样的,均是遍历GC Roots,然后将存活的对象标记。

            整理:移动所有存活的对象,且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收。因此,第二阶段才称为整理阶段

    (4)分代收集算法

        根据内存分代选择不同的收集算法

        新生代中:每次垃圾回收都会发现有大批对象死去,那么就采用复制算法

        老年代中:对象成活率高,没有额外空间对它进行分配担保,采用标记-清除或标记整理算法

    2.垃圾回收器

    (1)seria

        最基本,发展最悠久的(采用复制算法)

        单线程的垃圾收集器(gc线程在执行的时候用户线程停止)

        应用:桌面应用(占用内存小,所以收集会很快,用户无感知)

        

    (2)parnew

        多线程收集器(采用复制算法)

        多个收集器并发执行,减少 了收集时间

        

    (3)CMS(concurrent mark sweep)

        用于对老年代的回收(标记-清除算法)

        默认采用parnew作为新生代回收器

        工作过程:初始标记    并发标记    重新标记    并发清理 

        优点:并发收集 低停顿

        缺点:占用大量CPU 无法处理浮动垃圾 空间碎片

   

  (4)parallel

    多线程收集器(复制算法),新生代收集器

    达到可控制的吞吐量(也就是可以控制垃圾回收的时间)

    吞吐量 = 用户执行程序所用时间/(用户执行程序所用时间+垃圾回收时间)

    

  (5)G1收集器

     过程:(1)初始标记 (2)并发标记 (3)最终标记 (4)筛选回收

    G1垃圾收集器采用的是区域化,分布式的垃圾收集器,其核心思想是将整个堆内存划分为大小相同的子区域(region),这样Eden,Survivor,Tenured就变为了一系列不连续的内存区域,也就避免了全内存的gc操作

    G1中不再区分所谓的年轻代,老年代内存空间

    优点:能够像CMS收集器一样跟应用线程并行操作,更加精准的预测GC停顿时间

转载请注明原文地址: https://www.6miu.com/read-1900141.html

最新回复(0)