这个问题,面试被问到的概率还是很大的。以下关于 如何判断一个对象是否存活 的回答,完全参照《深入理解Java虚拟机》一书,有需要的可以看书学习。以下是题目解析

判断对象是否存活的算法包括:

  • 引用计数算法

  • 可达性分析算法

问题的回答就是通过引用计数算法或者可达性分析算法去判断一个对象是否存活,下面开始具体描述这两种算法。

引用计数算法(Reference Counting)

给对象中添加一个引用计数器,每当有一个地方引用它时,计数器加1;当引用失效时,计数器值减1;任何时刻计数器为0的对象就是不能再被引用的。

例如Object-C,Python语音使用引用计数算法进行内存管理。Java虚拟机没有选用引用计数器算法来管理内存,其中最主要的原因是它很难解决对象之间相互循环引用的问题。

对象循环引用代码示例:

public class ReferenceCountingGC {
public Object instance = null; public static void testGC() {
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA; objA = null;
objB = null; // 假设在这行发生GC, objA 和 objB是否能被回收?
System.gc();
}
}

对象objA和objB都有字段instance,赋值令 objA.instance = objB及objB.instance = objA,除此之外,这两个对象再无任务引用,实际上这两个对象已经不可能再被访问,但是它们因为相互引用着对方,导致它们的引用计数都不为0,于是引用计数算法无法通知GC收集器回收它们。

可达性分析算法(Reachability Analysis)

可达性分析算法的基本思路是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Root没有任何引用链相连时,则证明此对象是不可用的。

生存还是死亡

即使在可达性分析算法中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行可达性分析后发现没有与GC Roots相连接的引用,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。

如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会放置在一个叫做F-Queue的队列之中。并在稍后由一个虚拟机自动建立的,低优先级的Finalizer线程去执行它。这里所谓“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束,这样做的原因是,如果有一个对象在finalize()方法中执行缓慢,或者发生死循环,将可能会导致F-Queue队列中其他对象永久处于等待,甚至导致整个内存回收系统崩溃。

finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象这个时候,未被重新引用,那它基本上就真的被回收了。

回收方法区

Java虚拟机规范中确实说过可以不要求虚拟机在方法区中实现垃圾回收,而且在方法区中进行垃圾回收的“性价比”一般比较低,方法区的垃圾收集主要回收两部分内容:废弃的常量和无用的类。

废弃的常量,以常量池中字面量的回收为例,假如一个字符串“abc”已经进入常量池中,但是当前系统已经没有任何一个String对象叫做“abc”的,也没有任何其他地方引用这个字面量,这个“abc”常量就会被清理出常量池。

判断一个无用的类需要同时满足下面3个条件才能算是“无用的类”

  • 该类的所有实例都已经被回收

  • 加载该类的ClassLoader已经被回收

  • 该类对应的java.lang.Class对象已经没有任何地方被引用,无法在任何地方通过反射访问该类的方法。

【26期】如何判断一个对象是否存活?(或者GC对象的判定方法)?的更多相关文章

  1. js面试之--判断一个对象是不是数组类型,一共几种方法???

  2. 判断一个对象是否为真 __nonzero__ 方法和 __len__方法

    class A(): def __nonzero__(self): # 判断 一个对象是否为空,先查看该方法的返回值 return 1 def __len__(self): # 如果没有上一个方法,那 ...

  3. erlang中判断进程是否存活

    一个参数的方法是已知Pid判断进程是否存活.两个参数的方法是已知节点和Pid或进程名判断进程是否存活. is_process_alive(Pid) when is_pid(Pid)->rpc:c ...

  4. jvm高级特性(2)(判断存活对象算法,finaliza(),方法区回收)

    JVM高级特性与实践(二):对象存活判定算法(引用) 与 回收 垃圾回收器GC(Garbage Collection) 于1960年诞生在MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语 ...

  5. GC是如何判断一个对象为"垃圾"的?被GC判断为"垃圾"的对象一定会被回收吗?

    一.GC如何判断一个对象为”垃圾”的java堆内存中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”.那么GC具体通过什么手段来 ...

  6. JS心得——判断一个对象是否为空

    判断一个对象是否为空对象,本文给出三种判断方法: 最常见的思路,for...in...遍历属性,为真则为"非空数组":否则为"空数组" 2.通过JSON自带的. ...

  7. javascript-如何判断一个对象为数组

    Q:如何判断一个对象是否为数组? A1:判断对象的constructor是否指向Array, 接着判断对应的特殊属性,如length,splice之类.这个很容易冒充. A2:使用instanceof ...

  8. 使用js判断一个对象是否为空 比如 obj={}

    今天使用到js判断一个对象是否为空,js没有封装好的方法,这里最好的办法就是使用jquery里面的封装好的方法 $.isEmptyObject(obj)

  9. js如何判断一个对象是不是Array?(转载)

    js如何判断一个对象是不是Array? 在开发中,我们经常需要判断某个对象是否为数组类型,在Js中检测对象类型的常见方法都有哪些呢? typeof 操作符 对于Function, String, Nu ...

  10. 如何判断一个对象是否为jquery对象

    当我们在用jquery的each做循环遍历的时候常常会使用到this 而有时候我们不知道this所指的到底是什么,因为要使用jquery 的方法 前提此对象必须是jquery对象. 另外要判断一个ja ...

随机推荐

  1. 线性构造treap

    数据结构 线性构造treap treap的线性构造可以使复杂度锐减到\(O(n)\),很优秀 treap的本质就是小根堆+二叉搜索树,即保证val满足搜索树的同时,维护rad的小根堆. 现在我们先把数 ...

  2. [NOIP2017 普及组]跳房子 【题解】

    题目背景 NOIP2017 普及组 T4 题目描述 跳房子,也叫跳飞机,是一种世界性的儿童游戏,也是中国民间传统的体育游戏之一. 跳房子的游戏规则如下: 在地面上确定一个起点,然后在起点右侧画 \(n ...

  3. pymysql在读取bit类型时显示x00的解决办法

    #用于转换bit在pymysql中显示为x00的问题from pymysql import convertersconverions = converters.conversionsconverion ...

  4. Coolify系列02-从0到1超详细手把手教你上手Coolify

    接着上集(Coolify系列01- 从0到1超详细手把手教你上手Heroku 和 Netlify 的开源替代方案 ),此时我们已经运行成功,如果没有成功,可以参考我的Coolify系列其他文章来解决问 ...

  5. Typora 最后一个免费版本

    介绍 Typora 是一款轻量级的 Markdown 编辑器,其最为出众的特点是: 所见即所得. Typora 于2021年11月23日推出了第一个正式版,并转为收费.不过价格也算合理,89元/3台设 ...

  6. Unity_UIWidgets - 组件Scaffold

    UIWidgets - 组件Scaffold 各位兄弟姐妹,想通过Unity来开发UIWidgets的么,想通过UIWi的gets..来开发手机APP么??想么想么,哈哈哈哈哈哈哈哈. 好了,小黑不唠 ...

  7. Python中的函数定义中的斜杠/和星号*

    Python中的函数定义中的斜杠/和星号* 示例 看一段代码  def say_hello(name,age=18):     print(f'你好!我是{name},今年我{age}啦.') say ...

  8. redis-07主从复制

    转 https://www.jianshu.com/p/06ab9daf921d https://www.jianshu.com/p/06ab9daf921d 1 基本说明 我们所说的主从复制,主机数 ...

  9. springboot返回数据null参数设为空字符串或空数组

    package com.ruoyi.framework.config.ResponseVoConfig.WebConfig; /** * @Classname MyJsonMapper * @Desc ...

  10. 不花钱几分钟让你的站点也支持https

    前言 现在,免费SSL证书已经很普遍了,但是,申请和配置SSL证书仍然是一件较为繁琐的事,修改web服务配置在所难免,且不同的web服务配置方法不一样,不具备通用性.本文介绍一种通用的快速配置方法,w ...