【JVM】JVM 是如何进行垃圾回收的?

背景:如果把每一种编程语言比作一种交通工具的话,那Java肯定是自动挡,这得益于Java的 JVM 中的垃圾回收机制。当堆内存区域被对象占满时,会自动的进行垃圾回收,释放内存空间。下面我们对Java中的垃圾回收进行具体的介绍。

一、JVM 堆内存区域划分

  • 为了提高垃圾回收的效率,JVM 内存被划分成新生代、老年代这2大部分(JDK1.8),这两部分的划分大小比例为1:2;
  • 其中,新生代部分的内存又被分成了Eden区、Suvivor0区、Suvivor1区(或者SuvovorFrom区,SuvovorTo区),大小比例为 8:1:1,该部分的比例可调整,通过 -XX: SurvivorRatio 参数进行调整;

在这里插入图片描述

二、堆内存各区域之间关系

  • 堆内存各部分之间的关系在某种程度上可以理解为串联的关系。这里打个不恰当的比方:把一个内存实例看作一个游戏角色,它一开始诞生在 Eden 区,通过升级打怪会进入到 Suvivor 区,进而进入到老年代。
  • JVM中的对象实例大部分都存活时间很短,基本上朝生暮死,大部分都抗不过一次GC。而那些经过多次GC而仍然存活的对象,在下一次GC来临时大概率还会继续存活。
  • 对象的生命周期。对象一般在Eden区进行创建,如果Eden区满了,会触发一次Young GC。此次存活下来的对象会被转移到Suvivor区(Suvivor0区或者Suvivor1区)。如果Suvivor区的内存被占满的话也会触发GC,在Suvivor区经过多次GC的对象或者满足其他条件的,会被转移到老年代。

在这里插入图片描述

三、对象进入老年代满足的条件

对象进入老年代内存区域分为以下3种,满足其一即可:

  • 撑过了15次GC。对象是有年龄的,每经过一次GC,存活的对象的年龄就会+1。经过15次 GC 仍然存活的对象会被转移到老年代。具体的次数可以通过 JVM 参数-XX: MaxTenuringThreshold 进行调整。
  • 大对象可以直接进入老年代。通过JVM 参数 -XX:PretenureSizeThreshold 参数设置大对象的阈值,大于该阈值的对象可以视为大对象,可直接进入老年代。
  • 基于对象年龄的动态判断。条件:如果Survivor区小于等于某个年龄的对象大小之和大于Survivor 区内存大小的一半,那么可以将大于该年龄的对象转移到老年代。

四、Minor GC、Major GC 和 Full GC 的触发条件

1. Minor GC 触发条件

Minor GC又叫做Young GC,Eden区内存占满时就会触发一次MinorGC。

2. Major GC 触发条件

Major GC 集中在老年代,老年代区域内存占满时就会触发一次Major GC,如果老年代内存还是不够就会触发Full GC,如果还不够的话就会抛OOM。

3. FullGC 触发条件

Full 涵盖了整个堆空间,包含了方法区。

  • 老年代空间不足时会触发Full GC。例如,在将年轻代的对象转移到老年代时发现空间不足,就会触发一次 Full GC。或者在创建一个大对象时,该对象的大小超过了阈值,就会触发Full GC。
  • 永久代空间不足触发Full GC。在存在永久代的情况下,如果在永久代分配内存发现内存不够,也会触发一次Full GC。
  • 源代码中的 System.gc() 方法,可能会触发Full GC,但是不一定。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值