版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/carson_ho/article/details/102540797
Java对象存活的方式,希望你们会喜欢
Java堆里的对象 是否进行回收的判断准则:Java对象是存活 or 死亡判断对象为死亡才会进行回收
Java虚拟机中,判断对象是否存活有2种方法: 下面会进行详细介绍。
Java 对象添加一个引用计数器当计数器不为 0 时,判断该对象存活;否则判断为死亡(计数器 = 0)。
即该算法存在判断逻辑的漏洞
<-- 背景 -->
// 对象objA 和 objB 都有字段 name
// 两个对象相互进行引用,除此之外这两个人对象没有任何引用
objA.name = objB;
objB.name = objA;
<-- 问题 -->
// 实际上这两个对象已经不可能再被访问,应该要被垃圾收集器进行回收
// 但因为他们相互引用,所以导致计数器不为0,这导致引用计数算法无法通知垃圾收集器回收该两个对象正由于该算法存在判断逻辑漏洞,所以 Java虚拟机没有采用该算法判断Java是否存活。
Java、C#)都采用 引用链法 判断 Java对象是否存活。将一系列的 GC Roots 对象作为起点,从这些起点开始向下搜索。
GC Root 的对象有:
1.Java虚拟机栈(栈帧的本地变量表)中引用的对象
2.本地方法栈 中 JNI引用对象
3.方法区 中常量、类静态属性引用的对象如下图:

当一个对象到 GC Roots 没有任何引用链相连时,则判断该对象不可达
没有任何引用链相连 =
GC Root到对象不可达 = 对象不可用

不可达对象会被放在”即将回收“的集合里。
a. 不筛选:继续留在 ”即将回收“的集合里,等待回收; b. 筛选:从 ”即将回收“的集合取出
finalize()方法 当对象无
finalize()方法 或finalize()已被虚拟机调用过,则视为“没必要执行”
当对象经过了第一次的标记 & 筛选,会被进行第二次标记 & 准备被进行 筛选
该对象会被放到一个 F-Queue 队列中,并由 虚拟机自动建立、优先级低的Finalizer 线程去执行 队列中该对象的finalize()
finalize()只会被执行一次finalize()运行结束。这是为了防止 finalize()执行缓慢 / 停止 使得 F-Queue队列其他对象永久等待。在执行finalize()过程中,若对象依然没与引用链上的GC Roots 直接关联 或 间接关联(即关联上与GC Roots 关联的对象),那么该对象将被判断死亡,不筛选(留在”即将回收“集合里) 并 等待回收
3步骤 + 以下流程

JVM的文章,具体如下;