当前位置: > 财经>正文

JVM是如何判断对象可回收?常见的GC算法有哪些? 黄金回收的算法有哪些类型的

2023-09-07 03:00:53 互联网 未知 财经

JVM是如何判断对象可回收?常见的GC算法有哪些?

一、在java中如何判断对象是否死亡?死亡意味着可以被回收 1、引用计数法算法:

给每一个对象添加一个引用计数器,当一个引用指向对象,计数器值加一,当一个引用失效,计数器减一,判断计数器是否为0,确定对象是否可用。

问题:

很难解决对象间的互相引用。 2、引用不可达算法:通过可达性分析判断对象是否存活。

通过 GC Roots对象作为起始点,开始向下搜索,当一个对象到GC Roots没有任何引用链相连时,则证明此对象时不可用。

java语言在可作为GC Roots的对象包括以下几种:为什么?

1、虚拟机栈(栈帧中的局部变量表)中的引用的对象 。 2、方法区中类静态属性引用的对象。 3、方法区中常量引用的对象。 4、本地方法栈中JNI(Native方法)引用的对象。

以上这四种区域的对象,虚拟机不会主动的回收。所以适合做GC Roots对象。

注意: 以上判断对象是否死亡,所提到的引用都是指强引用

1.是不是GC Roots不可达的对象,就一定是死亡、可回收的对象呢?为什么? 不是通常一个对象被判定为死亡、可回收最少要经历两次标记过程:1.当对象GC Roots不可达,则被第一次标记,并且进行一次筛选,条件是对象是否有必要执行finalize()方法。2.如果对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,则判定为没必要执行,对象会直接标记为死亡可回收。如果有必要执行finalize()方法,对象被放入一个F-Queue的队列中,执行finalize()方法,如果对象在finalize()方法执行过程中,又有引用指向他,那么第二次标记的时候对象将被移除即将回收的集合。

每个对象的finalize()方法,只会被系统自动调用一次。

二、垃圾回收算法 1、标记-清除算法: 标记-清除算法分为两个步骤:1、标记:标记出可回收的对象。方法采用的是可达性分析算法。(1.GC 不可达。2.执行finalize()方法,对象未逃脱)2、清除:标记后统一回收所有被标记的对象。

缺点:

1.标记和清除两个过程效率都不高。2.清除后会产生大量、不连续的内存碎片。(当程序需要分配一个大的对象时比如数组,无法找到足够连续的内存,不得不提前触发另一次垃圾收集动作) 2、复制算法:

新生代分为3个区域,eden 、from survivor(s0)、to survivor(s1),容量通常8:1:1。

* 复制算法发生在新生代;* 新生代分为eden、s0、s1三个区域;* S0和S1每次GC只使用其中一个区域;* 当发生minor GC时,将Eden、s0中存活的对象复制到s1中,之后将s1和s0交换。每次保证一个survivor区是空的;* survivor区中的对象每经过一次minor GC之后存活下来的对象的年龄都会+1,新生代中的对象年龄大于某一个值(默认15,可配置)后,会被复制到老年代中。

问题:

如果minor GC后S1空间不够存放eden和S0的数据时,怎么办?

这些对象将通过分配担保机制进入老年代。

优点:

效率高、不会产生内存碎片。

缺点:

1、空间利用率低。始终有一个survivor区为空。2、当对象存活率较高时,需要较多的复制操作。

补充

内存的分配与回收策略: 1、对象优先在Eden区分配;

大多数情况下,对象会优先在新生代的Eden区分配。当Eden区没有空间时,会触发minor GC 。当survivor区域中的不能够放下,来自Eden的对象。通过分配担保机制转移到老年代中。

2、大的对象直接进入老年代;

所谓大的对象是指,需要大量连续空间的对象。比如数组对象。

3、长期存活的对象将会进入老年代;

在新生代中的对象,每经过一次minor GC仍然存活对象的年龄都会+1,当年龄大于某个值(默认15,可配置)之后,就会进入老年代。

4、动态对象年龄分配;

survivor空间中的相同年龄的所有对象的大小总和 > survivor空间的一半,年龄大于等于这个年龄的对象会进入老年代。

5、空间分配担保;

当新生代的Eden区的对象由于survivor区的装不下而需要进入老年代的时候,

首先判断老年代的最大可用连续空间是否大于新生代所有对象总空间。大于则Eden区的Minor GC 是安全的。 否则看虚拟机是否允许担保失败,允许则继续查看老年的最大连续空间是否大于历次晋升到老年代的对象的平均大小,大于可尝试minor GC , 小于或者不允许担保失败,这时老年代需要进行一次Full GC.

3、标记-整理算法(老年代采用) 先标记可回收对象,之后让存活的对象移动到一端,清理掉边界以外的内存。

缺点:

在标记-清除算法基础上增加整理,需要数据移动。成本较高。

优点:

不会产生内存的碎片 4、分代收集算法

根据对象的存活周期的不同,将heap分为新生代和老年代。这样可以根据各个代的不同特点选取合适的回收算法。

1、新生代,对象的存活周期通常很短,每次minor GC 都有大量的对象死去,存活下来的对象通常很少,所以采用复制算法进行垃圾回收。只需复制较少的对象便可实现。 2、老年代,对象的存活周期通常很长,没有额外的空间分配担保,所以必须使用标记-整理或者标记-清除算法进行回收。 三种算法比较:

效率: 复制 > 标记整理 > 标记清除 (此处的效率只是简单的对比时间复杂度,实际情况不一定如此)

内存整齐度: 复制 = 标记整理 > 标记清除

内存利用率: 标记整理 > 标记清除 > 复制

版权声明: 本站仅提供信息存储空间服务,旨在传递更多信息,不拥有所有权,不承担相关法律责任,不代表本网赞同其观点和对其真实性负责。如因作品内容、版权和其它问题需要同本网联系的,请发送邮件至 举报,一经查实,本站将立刻删除。