美文网首页Android开发Android开发Android
JVM:判断一个Java对象是否存活

JVM:判断一个Java对象是否存活

作者: Carson带你学安卓 | 来源:发表于2018-09-26 09:13 被阅读589次

前言

  • 如何判断一个Java对象是否存活对于垃圾回收、防止内存泄漏等十分重要
  • 本文将全面讲解判断Java对象存活的方式,希望你们会喜欢

在接下来的日子,我会推出一系列讲解JVM的文章,具体如下;感兴趣可持续关注Carson_Ho的安卓开发笔记

示意图

目录

示意图

1. 判断方式

  • 垃圾收集器对 Java堆里的对象 是否进行回收的判断准则:Java对象是存活 or 死亡

判断对象为死亡才会进行回收

  • Java虚拟机中,判断对象是否存活有2种方法:
    1. 引用计数法
    2. 引用链法(可达性分析法)

下面会进行详细介绍。


2. 引用计数法

2.1 方式描述

  • Java 对象添加一个引用计数器
  • 每当有一个地方引用它时,计数器 +1;引用失效则 -1;

2.2 判断对象存活准则

当计数器不为 0 时,判断该对象存活;否则判断为死亡(计数器 = 0)。

2.3 优点

  • 实现简单
  • 判断高效

2.4 缺点

  • 无法解决 对象间相互循环引用 的问题

即该算法存在判断逻辑的漏洞

  • 具体描述
<-- 背景 -->
// 对象objA 和 objB 都有字段 name
// 两个对象相互进行引用,除此之外这两个人对象没有任何引用
objA.name = objB;
objB.name = objA;

<-- 问题 -->
// 实际上这两个对象已经不可能再被访问,应该要被垃圾收集器进行回收
// 但因为他们相互引用,所以导致计数器不为0,这导致引用计数算法无法通知垃圾收集器回收该两个对象

正由于该算法存在判断逻辑漏洞,所以 Java虚拟机没有采用该算法判断Java是否存活。


3. 引用链法(可达性分析法)

  • 很多主流商用语言(如JavaC#)都采用 引用链法 判断 Java对象是否存活。
  • 含3个步骤:
    1. 可达性分析
    2. 第一次标记 & 筛选
    3. 第二次标记 & 筛选

3.1 可达性分析

a. 方式描述

将一系列的 GC Roots 对象作为起点,从这些起点开始向下搜索。

  • 可作为 GC Root 的对象有:
    1.Java虚拟机栈(栈帧的本地变量表)中引用的对象
    2.本地方法栈 中 JNI引用对象
    3.方法区 中常量、类静态属性引用的对象
  • 向下搜索的路径 = 引用链

如下图:

示意图

b. 判断 对象是否可达 标准

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

没有任何引用链相连 = GC Root到对象不可达 = 对象不可用

示意图

特别注意

  • 可达性分析 仅仅只是判断对象是否可达,但还不足以判断对象是否存活 / 死亡
  • 当在 可达性分析 中判断不可达的对象,只是“被判刑” = 还没真正死亡

不可达对象会被放在”即将回收“的集合里。

  • 要判断一个对象真正死亡,还需要经历两个阶段:
    1. 第一次标记 & 筛选
    2. 第二次标记 & 筛选

3.2 第一次标记 & 筛选

  • 对象 在 可达性分析中 被判断为不可达后,会被第一次标记 & 准备被筛选

a. 不筛选:继续留在 ”即将回收“的集合里,等待回收;
b. 筛选:从 ”即将回收“的集合取出

  • 筛选的标准:该对象是否有必要执行 finalize()方法
    1. 若有必要执行(人为设置),则筛选出来,进入下一阶段(第二次标记 & 筛选);
    2. 若没必要执行,判断该对象死亡,不筛选 并等待回收

当对象无 finalize()方法 或 finalize()已被虚拟机调用过,则视为“没必要执行”


3.3 第二次标记 & 筛选

当对象经过了第一次的标记 & 筛选,会被进行第二次标记 & 准备被进行 筛选

a. 方式描述

该对象会被放到一个 F-Queue 队列中,并由 虚拟机自动建立、优先级低的Finalizer 线程去执行 队列中该对象的finalize()

  1. finalize()只会被执行一次
  2. 但并不承诺等待finalize()运行结束。这是为了防止 finalize()执行缓慢 / 停止 使得 F-Queue队列其他对象永久等待。

b. 筛选标准

在执行finalize()过程中,若对象依然没与引用链上的GC Roots 直接关联 或 间接关联(即关联上与GC Roots 关联的对象),那么该对象将被判断死亡,不筛选(留在”即将回收“集合里) 并 等待回收


3.4 总结

3步骤 + 以下流程


示意图

4. 总结

  • 本文全面讲解判断Java对象存活的方式
  • 在接下来的日子,我会推出一系列讲解JVM的文章,具体如下;感兴趣可持续关注Carson_Ho的安卓开发笔记
示意图

请点赞!因为你的鼓励是我写作的最大动力!

相关文章阅读
Android开发:最全面、最易懂的Android屏幕适配解决方案
Android事件分发机制详解:史上最全面、最易懂
Android开发:史上最全的Android消息推送解决方案
Android开发:最全面、最易懂的Webview详解
Android开发:JSON简介及最全面解析方法!
Android四大组件:Service服务史上最全面解析
Android四大组件:BroadcastReceiver史上最全面解析


欢迎关注Carson_Ho的简书!

不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度

相关文章

  • JVM之判断对象的存活状态

    jvm垃圾收集器在进行垃圾回收时,会判断对象是否存活状态,只有死去的对象才会被回收。那么怎么判断对象的存活状态呢?...

  • JVM:判断一个Java对象是否存活

    前言 如何判断一个Java对象是否存活对于垃圾回收、防止内存泄漏等十分重要 本文将全面讲解判断Java对象存活的方...

  • JVM对象存活判断

    垃圾回收的三个核心问题: 哪些内存需要回收? 什么时候回收? 如何回收? 一、对象存活判断 1.1、引用计数算法 ...

  • JVM - 判断对象是否存活算法

    在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在堆进行回收前,第一件事情就是要确定这些对象之中哪些还“...

  • JVM--判断对象是否存活

    (1)引用计数法 思想:为每个对象添加一个引用计数器,每当有一个地方引用这个对象时,计数器的值就+1,;当引用失效...

  • 《深入理解jvm》读书笔记之——判断对象存活的方法

    1、对象的状态 对于jvm中的垃圾收集器中,判断对象是否可以被回收,哪些对象是否需要存活是有以下的方法的。 1.1...

  • 垃圾收集--引用(2)

    根据上篇文章可知垃圾收集--判断对象是否存活 - 简书,判断对象是否存活和“引用”有关。 在JDK...

  • GC算法

    主要关注点: 对象存活判断 GC算法 垃圾回收器 对象存活判断 判断对象是否存活一般有两种方式: 引用计数:每个对...

  • Java GC 判断对象是否存活

    Java对象是否存活的判断算法——根搜索算法。这个算法的思路其实很简单,它把内存中的每一个对象都看作一个节点,并且...

  • Java的强引用、软引用、弱引用和虚引用

    前言 Java执行GC判断对象是否存活有两种方式,其中一种是:引用计数。 引用计数:Java堆中每一个对象都有一个...

网友评论

  • 1999c1b720cd::+1:🏻。如果最后能结合具体源码分析一下更好。

本文标题:JVM:判断一个Java对象是否存活

本文链接:https://www.haomeiwen.com/subject/jryhtxtx.html