GC学习总结

目录

回收判定

        1.引用计数 ReferenceCount

        2.可达性 RootSearching --主流

常见的垃圾回收算法

        1.标记清除法

        2.拷贝算法

        3.标记压缩

回收无效对象过程

方法区内存回收

GC算法

1.标记清除算法

2.拷贝算法

解决空间利用率

分配担保

3.标记整理算法--老年代GC算法

4.分代收集算法


回收判定

        1.引用计数 ReferenceCount

                一个对象a被一个变量或对象引用时,a对象对应的引用计数器加一,当前引用失效后计数器减一,若a对象的计数器归0,则代表无引用指向a对象,a为无效对象。

                补充:引用计数无法解决对象之间相互循环引用问题

        2.可达性 RootSearching --主流

                可达性分析中,定main()方法中创建的对象为根节点, 若直接或间接和根节点关联,视该对象为可达,非无效对象。若与根节点无关联性,但其引用计数器非0,实则也是无效对象,需要被垃圾回收。


常见的垃圾回收算法

        1.标记清除法

                --位置不连续,产生碎片,效率偏低(两次扫描)。

        2.拷贝算法

                --不产生碎片,浪费内存。

        3.标记压缩

                --没有碎片,效率偏低,两次扫描,指针需要调整。


回收无效对象过程

判断该对象是否覆盖了finalize()方法
若已覆盖,且该对象的finalize()方法还未被执行过,那么就会将finalize()扔到F-Queue队列中;
若未覆盖或已调用过finalize()方法,则直接释放对象内存
执行F-Queue队列中的finalize()方法
虚拟机会以较低的优先级执行这些finalize()方法们,也不会确保所有的finalize()方法都会执行结束.如果finalize()方法中出现耗时操作,虚拟机就直接停止执行,将该对象清除
对象重生或死亡
如果在执行finalize()方法时,将this赋给了某一个引用,那么该对象就重生了.如果没有,那么就会被垃圾收集器清除.

补充:finalize()方法开销大,不确定性大,不能确定调用对象的顺序,不建议使用。

          建议使用try-finally或其他方法回收垃圾


方法区内存回收

        1.废弃常量

                --和回收废弃对象类似,如常量a不被任何变量或对象引用,则会被清除。

        2.废弃的类

                --1.判断类的所有对象实例是否都被回收,java Heap中不存在该类的实例

                --2.加载该类的类加载器--classLoader被回收

                --3.该类的字节码对象java.lang.Class未被其他对象或变量引用。


GC算法

1.标记清除算法

                --最基础的收集算法

                --缺陷:效率不高,标记回收后存在大量内存碎片,降低空间利用率

        1.判断需要回收的数据,然后标记;

        2.回收被标记的数据;


2.拷贝算法

        将内存等分为两份,设为a,b,存储数据时只在a上存储。当需要回收时,将a上的废弃数据标记,将有用的数据复制到b上,将a上的数据全部回收。

        --优缺点:避免了空间中存在内存碎片,但内存少了一半且效率不高。

解决空间利用率

         --新生代中,大部分对象存活时间很短,经过一次垃圾回收后只存在少量对象,所以底层中新生代(堆)内存被分为了3块:edan,s1,s2(分配比例8:1:1)。

解决方案:分配内存时只使用edan和s1,当edan和survivor1空间将满时,JVM会发动一次minorGC,清除掉废弃对象,并将所有存活下来的对象移动到Survior2中.接下来就使用Survior2+Eden进行内存分配.通过这种方式,只需要浪费10%的内存空间即可实现带有压缩功能的垃圾收集方法,避免了内存碎片的问题

分配担保

        --当JVM为一个对象分配内存空间时,发现edan+survior中空闲部分装不下该对象,会触发minorGC,但若minorGC后仍内存空间仍然无法装下该对象,JVM会将edan+survior中的对象移到老年代中,再将新对象存入edan。

--

 1、准备在新生代进行minorGC时,首先检查“老年代”最大连续空间区域的大小是否大于新生代所有对象的大小。

    2、如果老年代能装下所有新生代对象,minorGc没有风险,进行minorGC

    3、老年代无法装下,垃圾收集器进行一次预测:根据以往minorGC过后存活对象的平均数来预测这次minorGC后存活对象的平均数。

    (1)以往平均数小于当前老年代最大的连续空间,就进行minorGC,

    (2)大于,则进行一次fullGC,通过清楚老年代中废弃数据来扩大老年代空闲空间,以便给新生代做担保。


3.标记整理算法--老年代GC算法

        --判断需要回收的数据,然后标记

        --将有效对象移动到另一端,然后清理掉端边界外的其他对象。


4.分代收集算法

        --老年代中对象存活率高,无额外空间对其分配担保,必须使用"标记-清理"或"标记-整理"算法;

        --新生代中存放"朝生夕死"的对象那就用复制算法,只需要付出少量存活对象的复制成本就可以完成收集.

        总结:老年代使用标记-清理或标记-整理算法;新生代使用拷贝算法。


内存溢出

        --随着老年代内的数据逐渐增多,老年代内存也会放满,字节码执行引擎会执行Full GC。会对整个堆执行对象回收,若未回收到对象,老年代还是满得,同时survivor区还在向老年代内存放数据,就会产生异常数据报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值