[jvm解析系列][四]Java的垃圾回收(二)垃圾收集算法,内存分配和回收策略

上回说到如何鉴别一个垃圾。

这回咱们讲讲怎么收集垃圾收集垃圾有几种算法如下:

1、标记-清除算法

这个算法最为基础,我们先讲算法再说优缺点。

实现过程:

标记出所有需要回收的对象,当标记完成后统一回收。图解如下:

优缺点:

可能画出来图的时候大家都发现了,这个算法有一个很明显的问题,那就是大量的不连续的内存碎片,这样的内存碎片遇到大对象分配的时候很可能遇到内存不足的 情况,当然出了这个情况以外还有一种问题就效率太低(可以对比之后的算法)。

2、复制算法

实现:把内存划分为大小相等的两块,当GC的时候,就把其中一块复制到另一块上,然后直接清理掉原本的那一半内存。

优缺点

这种算法要比标记清除算法效率高并且没有内存碎片,但是这样会浪费一半内存而且如果存货较多对象,复制效率也很低。

修正与应用:

现在商业虚拟机大多都采用这种方式回收新生代,但是不回划一半内存那么大。它们把内存氛围Eden空间(80%)和两块Survivor空间(10%+10%),每次GC时, 从Eden和一个survivor区里复制活着的对象到另一个survivor里,因为新生代 GC频繁且效率高,所以一半清除后的对象一个survivor基本可以存下,但是如果空间不够 用,就会引起老年代的分配担保(在本章稍后讲解)。

3、标记-整理算法

实现:

让所有存活的对象向前端移动,最后清除后面的内存

优缺点

效率高于标记-清除算法,而且可以保证所有的内存都可以使用

应用:

这种算法可以有效的用在老年代中,因为老年代gc不频繁而且每次效率不高。

我们了解到了怎么清理内存之后,这在之前还有一个问题,分配对象的规则是什么呢

1、分配对象

我们用流程图来讲解:

1我们可以看出来一个对象在分配的时候先要看看Eden区是否可以装得下(或者设置了PretenureSizeThreshold参数,根据参数来判断)

2、如果装不下就直接分配到老年区

3、如果分配的下又会查询Eden空间是否是充足

4、如果Eden剩余可用内存充足就把对象放在了Eden区域

5、如果Eden不充足的话就会引起MinorGC(新生代GC,新生代GC效率较高大概是FullGC(老年代GC)的十倍),如果发现Eden中的对象不足以放在survivor中就 会直接放在老年代里,然后分配对象到新生代。

2、长期存活对象转入老年代

图解:

特殊情况

虚拟机中并没有严格的遵守必须年龄>=MaxTenuringThreshold才能转到老年代,如果Survivor空间中相同年龄所有对象大小的综合大雨Survivor空间的一半,年 龄>=它们的也可直接转到老年代。

3、空间分配担保

实现:

在MinorGC之前每次都会查看老年代的最大连续可用空间是不是大于新生代所有总对象总空间,如果大于的话说明新生代可以转入老年代,如果空间不足保证所有的 survivor区域里的话说明不安全,因为很有可能MinorGC后晋升老年代,老年代根本存不下,所以这个时候要查看是否设置了允许冒这个险,(参数 HandlerPromotionFailure)除了检测参数外还要查看是否大于以往晋升对象的平均值,都允许的话就开始冒险。如果不允许就先FullGC。

冒险:尝试把MinorGC后剩余的对象放入老年代,如果成功最好,省了FullGC,如果失败只能跑一次FullGC了,时间花销最大。

图解如下:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值