您的位置:首页 > 职场人生

jvm_垃圾回收学习笔记_1_如何判断对象已死?(附面试题)

2020-07-19 04:49 337 查看

一、引用计数法

    引用计数法顾名思义就是在对象中添加一个引用计数器,每当有其他对象引用它时计数器就+1。大概就是下图这个结构:

在线画图工具:ProcessOn


那么引用计数法有什么优点和缺点呢?我想着就是用一小部分空间换时间吧,这样他的效率高,只要计时器为0就可以回收了。但是仔细想想它也有缺点,就是无法解决循环依赖的问题,如下图所示:

此时A与B互相引用着,就算已经没有其他地方引用着A和B类,但是他们之间互相有引用,垃圾回收器就不能回收它们。
    此时我们可以做一个实验来测试一下。

这里用的是jdk14,默认是G1垃圾回收器,打印GC日志的参数是
-XX:+PrintGCDetails
,此时可以看到垃圾回收器是回收了这两个对象的(
Pause Full (System.gc()) 1M->0M(8M)
)。由此可见JVM不是通过引用计数法来判断对象是否已经死翘翘的~
这里笔者也没找到资料说明JVM是从什么版本开始弃用引用计数法的或者根本没有使用,有知道的大神可以在评论区说下~
那么JVM到底是怎么判断对象是否已死的呢?这就是要到下面要介绍的可达性分析算法了。

二、可达性分析算法

    可达性分析算法就是通过一堆已“GC Roots”的跟对象作为起始节点并且以这些节点开始根据引用关系向下搜索,搜索的过程称为‘引用链’。如果某个对象对GC Roots见没有任何引用关系,则判定改对象死亡。图解如下:

如图。Obj1-Obj4都可以追溯到GC roots对象,所以他们不会被回收;Obj5和Obj6虽然互相引用,但是并没有GC Roots对象引用他们,所以可以判定它们两已经死亡~

三、面试题

1、谈谈在jvm中如何判断一个对象是否死亡

    上面已分析,不在重复。

2、如何判断一个常量是否死亡,

    此题同

java单例对象会被回收吗?
大致相同。在JVM中,判断一个常量是否死亡的条件十分严格,有以下三个条件:

  1. 该类的所有实例以及其子类实例都已被回收
  2. 加载该类的类加载器被回收
  3. 该类的Class对象没有在任何地方被引用,也没有在任何地方通过反射调用该类
    只有同时满足以上三个条件的常量才会被回收。所以java单例对象基本上是不会被回收的。

3、什么对象可以作为GC Roots对象?

  1. 在虚拟机栈中被引用的对象
  2. 在方法区中类静态属性引用的对象
  3. 在方法区中常量引用的对象
  4. 本地方法栈中引用的对象(Native方法)
  5. Java虚拟机内部的引用,如Class对象,异常对象,类加载器等
  6. 被同步锁持有的对象
  7. 反映Java虚拟机内部情况的JMXBean、JVMTi中注册的回答、本地代码缓存等
    上面7个是查资料查到的。个人感觉作为普通程序员,记住前六个就好了~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: