关于后端:面试必问JVM-如何确定死亡对象

53次阅读

共计 2075 个字符,预计需要花费 6 分钟才能阅读完成。

在 JVM 中,有两个十分重要的知识点,一个是 JVM 的内存布局(JVM 运行时的数据区域),另一个就是垃圾回收。而垃圾回收中又有两个重要的知识点,一个是如何确定 JVM 中的垃圾对象,另一个是应用不同的垃圾收集器进行垃圾回收。而本篇要探讨的是前者,前面的内容咱们下一篇再聊。

垃圾对象的断定有两种罕用的算法:援用计数器算法和可达性剖析算法。

1. 援用计数器算法

援用计数算法(Reference Counting)属于垃圾收集器的晚期实现算法了,它指的是在创建对象时关联一个与之绝对应的计数器,当此对象被应用时加 1,相同销毁时 -1。当此计数器为 0 时,则示意此对象未应用,能够被垃圾收集器回收。

援用计数算法的优缺点很显著,其 长处是垃圾回收比拟及时,实时性比拟高 ,只有对象计数器为 0,则能够间接进行回收操作;而 毛病是无奈解决循环援用的问题,比方以下代码:

public class RefCounterTest {
    // 对象 A
    static class RefObjectA {
        private RefObjectB refObjectB;

        public void setRefObjectB(RefObjectB refObjectB) {this.refObjectB = refObjectB;}
    }
    // 对象 B
    static class RefObjectB {
        private RefObjectA refObjectA;

        public void setRefObjectA(RefObjectA refObjectA) {this.refObjectA = refObjectA;}
    }
    // 测试代码
    public static void main(String[] args) {RefObjectA objectA = new RefObjectA();
        RefObjectB objectB = new RefObjectB();
        objectA.setRefObjectB(objectB);
        objectB.setRefObjectA(objectA);
        objectA = null;
        objectB = null;
    }
}

如以上代码所示,即便是将 main 办法中的 objectA 和 objectB 都设置为 null,也就是这两个对象都彻底不应用了,然而因为二者存在互相援用的关系,所以它们所对应的对象计数器不为 0,这样循环援用导致垃圾数据无奈被革除的事件就产生了。

2. 可达性剖析算法

可达性剖析算法(Reachability Analysis)是目前支流虚拟机中,应用最宽泛的判断垃圾对象的实现算法,它指的是从对象的终点(GC Roots)开始向下搜寻,如果对象到 GC Roots 没有任何援用链相连时,也就是说此对象到 GC Roots 不可达时,则示意此对象能够被垃圾回收器所回收,如下图所示:

在 Java 语言中,可作为根节点(GC Roots)的对象有以下 4 类:

  1. Java 虚拟机栈中的援用对象,也就是 Java 虚拟机栈帧中,本地变量表所存储的(援用)对象。在 Java 虚拟机栈帧中存储的对象都是未来执行时,要应用的对象,所以和援用对象相干的对象都不能被回收;
  2. 本地办法栈中的援用对象 和 Java 虚拟机栈中的援用对象相似,也不能被回收;
  3. 办法区中类动态属性援用的对象 也能够作为 GC Roots;
  4. 办法区中常量援用的对象 也能够作为 GC Roots。因为常量是保留在常量池中的,属于全局可应用的对象,所以也能作为 GC Roots。

3. 无关“援用”

不论是援用计数法还是可达性剖析算法都与对象的“援用”无关,这阐明 对象的援用决定了对象的生死,而 Java 中的援用也比较复杂,它从 JDK 1.2 之后,(援用)分成了以下 4 种类型:

  • 强援用 :在代码中普遍存在的,相似 Object obj = new Object() 这类援用, 只有强援用还在,垃圾收集器永远不会回收掉被援用的对象
  • 软援用 :是一种绝对强援用弱化一些的援用,能够让对象豁免一些垃圾收集, 只有当 JVM 认为内存不足时,才会去试图回收软援用指向的对象,JVM 会确保在抛出 OutOfMemoryError 之前,清理软援用指向的对象
  • 弱援用 :非必须对象,但它的强度比软援用更弱, 被弱援用关联的对象只能生存到下一次垃圾收集产生之前
  • 虚援用 :也称为幽灵援用或幻影援用, 是最弱的一种援用关系,无奈通过虚援用来获取一个对象实例,为对象设置虚援用的目标只有一个,就是当着个对象被收集器回收时收到一条零碎告诉

总结

垃圾对象的断定有两种罕用的算法:援用计数器算法和可达性剖析算法。其中援用计数器算法实现简略、运行高效,然而存在循环援用的问题,所以支流的虚拟机应用的都是可达性剖析算法,可达性剖析算法是从对象的根节点 GC Roots 向下搜寻,如果根节点相连就是失常的对象,否则为垃圾对象能够被垃圾回收器回收。

本文已收录到 Gitee 开源仓库《Java 面试指南》,其中蕴含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、音讯队列等模块。Java 面试有它就够了:超全 Java 常见面试题,继续更新 …

正文完
 0