GC知识总结

一、什么是GC

GC就是垃圾回收机制, 在系统运行的时候,会产生一些无用的对象,他们占据着一部分内存, 所以需要GC去进行内存的释放,简而言之就是找到已经无用的对象,并把这些对象占用的空间收回使其可以重新利用.

二、什么时候执行GC

说到这个,我们需要先了解一下jvm结构、对象分配规则

                                         jvm结构

方法区(存放类信息、常量、静态变量、即时编译后的代码等数据。是所有线程共享区)--内存回收目标主要是针对常量池的回收和对类型的卸载。                                                                                                         

堆(存放对象实例。所有线程共享)--GC管理的主要区域,由年轻代和老年代组成,而年轻代内存又被分成三部分,Eden、From Survivor、To Survivor。                                                                                               

虚拟机栈(存放局部变量、执行环境、操作数栈)                                   

程序计算器(当前线程执行字节码的行号指示器)--一块较小的内存空间                                                                                                        本地方法栈(为虚拟机使用到的Native方法服务)                                   

对象分配规则

对象优先分配在Eden区,如果Eden区没有足够的空间,执行minor GC(后面会解释Minor GC 过程)

大对象直接进入老年代(大对象指需要大量连续内存空间的对象,一般引入的包会进入老年代)

长期存活的对象进入老年代,虚拟机为每个对象定义了一个年龄计数器,对象经过了1次GC 会被加入Survivor区,之后每经历一次年龄加一,直到达到阀值,对象进入老年区。

动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代。

空间分配担保。每次进行Minor GC时,JVM会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Monitor GC,如果false则进行Full GC。

从上面我们可以看出来Eden满了执行Minor gc,升到老年代的对象大于老年代剩余空间执行full gc,或者小于检查HandlePromotionFailure设置执行GC.  

三、Minor GC/Full GC

Minor GC 从年轻代空间回收内存,触发条件:当Eden区满时,触发Minor GC。

Full GC 清理整个堆空间,触发条件:(1)调用System.gc时,系统建议执行Full GC,但是不必然执行(2)老年代空间不足(3)方法区空间不足(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小

四、垃圾收集算法

首先我们先来看看垃圾判断算法

1)引用计数法(Reference Counting):许多教科书上判断对象是否存活都是这个算法,但是在主流的Java虚拟机里没有选用这个算法来管理内存,下面来简单介绍一下此算法,其实就是为对象中添加一个引用计数器,每当一个地方引用它时,计数器就加1;当引用失效时,计数器就减1;任何时刻计数器为0的对象就是不可能再被使用的

2)可达性分析算法(Reachability Analysis):在主流的商用程序语言的实现中,都是通过可达性分析法来判定对象是否存活的。这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的

1. 标记 - 清除

这种垃圾回收一次回收分为两个阶段:标记、清除。首先标记所有需要回收的对象,在标记完成后回收所有被标记的对象。这种回收算法会产生大量不连续的内存碎片,当要频繁分配一个大对象时,jvm在新生代中找不到足够大的连续的内存块,会导致jvm频繁进行内存回收(目前有机制,对大对象,直接分配到老年代中)

2.  复制算法

这种算法会将内存划分为两个相等的块,每次只使用其中一块。当这块内存不够使用时,就将还存活的对象复制到另一块内存中,然后把这块内存一次清理掉。这样做的效率比较高,也避免了内存碎片。但是这样内存的可使用空间减半,是个不小的损失。

3.  标记-整理算法

这是标记-清除算法的升级版。在完成标记阶段后,不是直接对可回收对象进行清理,而是让存活对象向着一端移动,然后清理掉边界以外的内存

4. 分代收集算法

当前的商业虚拟机的垃圾收集都是采用“分代收集”(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块。一般是把堆划分为新生代和老年代,这样就可以根据各个年代的特点采用最适合的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就采用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或者“标记-整理”算法来进行回收

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值