垃圾回收机制


前面提到,在程序运行过程中,垃圾回收主要发生在堆区,下面来看看堆区是怎么实现高效的垃圾回收的。

1 堆区的内存划分

为了进行高效的垃圾回收,JVM将java堆区划分为2个区,分别为年轻代、老年代。

1.1 新生代

主要是用来存放新生的对象,默认占据堆的1/3空间,即新生代与老年代之比为 1 : 2,可通过-XX:NewRatio设置。由于频繁创建对象,所以新生代会频繁触发MinorGC进行垃圾回收。

新生代又分为 Eden区、ServivorFrom、ServivorTo三个区,三者默认为8:1:1,通过-XX:SurvivorRatio设置

  • Eden区:Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。
  • ServivorTo:保留了一次MinorGC过程中的幸存者。
  • ServivorFrom:上一次GC的幸存者,作为这一次GC的被扫描者。

MinorGC:

MinorGC指发生在新生代的垃圾收集动作,非常频繁,回收速度也比较快。一般采用复制算法,如下:

  1. 首先,把Eden和ServivorFrom区域中存活的对象复制到ServicorTo区域(如果有对象的年龄以及达到了老年的标准,一般是15,则赋值到老年代区)
  2. 同时把这些对象的年龄+1(如果ServicorTo不够位置了就放到老年区)
  3. 然后,清空Eden和ServicorFrom中的对象;最后,ServicorTo和ServicorFrom互换,原ServicorTo成为下一次GC时的ServicorFrom区。

1.2 老年代

在新生代中存活很久或很大的对象,一般放在老年代区,老年代的对象比较稳定,所以MajorGC不会频繁执行。

当老年代内存空间不足时,触发MajorGC。

MajorGC:

MinorGC指发生在老年代的垃圾收集动作,很少执行,耗时较长。一般采用标记-清除算法,如下:

  1. 首先扫描一次所有老年代对象,标记出存活的对象
  2. 然后回收没有标记(引用)的对象

Full GC:

实际上这些术语在JVM规范并没有定义,只是我们根据现象和结果执行定义的,Full GC指清理整个堆空间(老年代+新生代)

1.3 方法区

经常提到的永久代(元空间)也就是方法区,虽然在物理上与堆共享内存,但实际上与堆相互隔离,因此JVM规范并不要求在方法区进行垃圾回收,但还是可以回收的。

方法区中存储者各种常量池、类元信息等,一般长时间存在,但也可能有一些失效的数据,出现以下情况时可以垃圾回收。

  • 常量池中的一些常量没有被引用,则会清理出常量池
  • 无用的类会被清理出方法区
    • 该类的实例被回收
    • 加载该类的ClassLoader被回收
    • 该类的Class对象没有被引用 (如没反射)

2. 垃圾对象判断算法

前面提到,在进行垃圾回收时都采用了标记—清除算法,那么怎么判断一个对象该不该回收呢?

2.1 引用计数法(已被淘汰,循环引用失效)

给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题。

2.2 可达性分析

这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。

可作为 GC Roots 的对象包括下面几种:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 本地方法栈(Native 方法)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 所有被同步锁持有的对象

注意:

  • 在可达性分析时,必须停顿所有Java线程。如果在分析过程中对象的引用关系在不断变化,则分析结果的准确性就无法得到保证。

2.3 可达性分析之三色标记法

为什么CMS的GC线程可以和用户线程一起工作?可达性分析不用暂停吗?这一切都是因为三色标记法

三色标记法是可达性分析法的一种,普通的可达性分析法需要停止用户线程,而三色标记法可以实现异步可达性分析。

CMS将对象标记为三种颜色:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值