说明:文章所有内容均摘自《深入理解Java虚拟机:JVM高级特性与最佳实践(第二版)》

在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”(即不可能再被任何途径使用的对象)。

1 引用计数算法

很多教科书判断对象是否存活的算法是这样的:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可能再被使用的。作者面试过很多的应届生和一些有多年工作经验的开发人员,他们对于这个问题给予的都是这个答案。

客观地说,引用计数算法(Reference Counting)的实现简单,判定效率也很高,在大部分情况下它都是一个不错的算法,也有一些比较著名的应用案例,例如微软公司的COM(Component Object Model)技术、使用ActionScript 3的FlashPlayer、Python语言和在游戏脚本领域被广泛应用的Squirrel中都使用了引用计数算法进行内存管理。但是,至少主流的Java虚拟机里面没有选用引用计数算法来管理内存,其中最主要的原因是它很难解决对象之间相互循环引用的问题。

举个简单的例子,请看代码清单3-1中的testGC()方法:对象objA和objB都有字段instance,赋值令objA.instance=objB及objB.instance=objA,除此之外,这两个对象再无任何引用,实际上这两个对象已经不可能再被访问,但是它们因为互相引用着对方,导致它们的引用计数都不为0,于是引用计数算法无法通知GC收集器回收它们。

/***testGC()方法执行后,objA和objB会不会被GC呢?*@author zzm*/
public class ReferenceCountingGC{public Object instance=null;private static final int_1MB=1024*1024;/***这个成员属性的唯一意义就是占点内存,以便能在GC日志中看清楚是否被回收过*/private byte[]bigSize=new byte[2*_1MB];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();}
}//运行结果
[Full GC(System)[Tenured:0 K->210K(10240K),0.0149142secs]4603K->210K(19456K),[Perm:2999K->
2999K(21248K)],0.0150007 secs][Times:user=0.01 sys=0.00,real=0.02 secs]
Heap
def new generation total 9216K,used 82K[0x00000000055e0000,0x0000000005fe0000,0x0000000005fe0000)
Eden space 8192K,1%used[0x00000000055e0000,0x00000000055f4850,0x0000000005de0000)
from space 1024K,0%used[0x0000000005de0000,0x0000000005de0000,0x0000000005ee0000)
to space 1024K,0%used[0x0000000005ee0000,0x0000000005ee0000,0x0000000005fe0000)
tenured generation total 10240K,used 210K[0x0000000005fe0000,0x00000000069e0000,0x00000000069e0000)
the space 10240K,2%used[0x0000000005fe0000,0x0000000006014a18,0x0000000006014c00,0x00000000069e0000)
compacting perm gen total 21248K,used 3016K[0x00000000069e0000,0x0000000007ea0000,0x000000000bde0000)
the space 21248K,14%used[0x00000000069e0000,0x0000000006cd2398,0x0000000006cd2400,0x0000000007ea0000)
No shared spaces configured.

从运行结果中可以清楚看到,GC日志中包含“4603K->210K”,意味着虚拟机并没有因为这两个对象互相引用就不回收它们,这也从侧面说明虚拟机并不是通过引用计数算法来判断对象是否存活的。

2. 可达性分析算法

在主流的商用程序语言(Java、C#,甚至包括前面提到的古老的Lisp)的主流实现中,都是称通过可达性分析(Reachability Analysis)来判定对象是否存活的。这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference  Chain),当一个对象到GC  Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。如图3-1所示,对象object 5、object 6、object 7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。

在Java语言中,可作为GC Roots的对象包括下面几种:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  • 方法区中类静态属性引用的对象。
  • 方法区中常量引用的对象。
  • 本地方法栈中JNI(即一般说的Native方法)引用的对象。

【深入Java虚拟机JVM 07】JVM如何判断对象已死相关推荐

  1. java判断对象已经被回收_Java中JVM判断对象已死的基本算法分析

    原标题:Java中JVM判断对象已死的基本算法分析 jvm中 有各种的垃圾收集器,每个收集器都有各自的算法. 但是一切的根本都需要找到找到应该被消除的对象,理解如何找到死亡对象才是理解垃圾收集器的基础 ...

  2. java判断对象已死_Java的JVM判断对象已死的基本算法分析

    jvm中有各种的垃圾收集器,每个收集器都有各自的算法.但是一切的根本都需要找到找到应该被消除的对象,理解如何找到死亡对象才是理解垃圾收集器的基础. 01两个基本算法 a.引用记数法:对象中加一个引用计 ...

  3. java判断对象已死_JVM判断对象已死亡?

    设计与实现以jvm为例+高级虚拟机 244.5元 (需用券) 去购买 > 本节常见面试题 如何判断对象是否死亡(两种方法). 简单的介绍一下强引用.软引用.弱引用.虚引用(虚引用与软引用和弱引用 ...

  4. python程序如何执行死刑图片_如何判断对象已死

    已死的对象就是不可能被任何途径使用的对象,有以下几种方法判断一个对象是否已经死了: 引用计数 给对象添加一个引用计数器,每当有一个地方引用他,计算器就加 1:当引用失效时,计数器减 1:任何时刻计数器 ...

  5. JVM 判断对象已死,实践验证GC回收

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  6. 【Java虚拟机规范】JVM类加载机制

    [Java虚拟机规范]JVM类加载机制 理论知识 一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载(Loading).验证(Verification).准备(Prep ...

  7. Java虚拟机学习(7):对象内存分配与回收

    对象优先在Eden上分配 大多数情况下,对象优先在新生代Eden区域中分配.当Eden内存区域没有足够的空间进行分配时,虚拟机将触发一次 Minor GC(新生代GC).Minor GC期间虚拟机将E ...

  8. Java虚拟机学习(6):对象访问

    对象访问会涉及到Java栈.Java堆.方法区这三个内存区域. 如下面这句代码: 1 Object objectRef = new Object(); 假设这句代码出现在方法体中,"Obje ...

  9. Java虚拟机详解----JVM常见问题总结

    [正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考本人之前的系列文章,尤其是那篇:Java虚拟机详解04----GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾 ...

最新文章

  1. DeepFake 新高度:一阶运动模型让“万物皆可动”
  2. MySQL在创建索引之前一定要想到的事情
  3. sql 忽略大小写_Flink使用Calcite解析Sql做维表关联(一)
  4. silverlight, 双击事件
  5. httpClient 处理SSL问题
  6. mac 上搭建gitlabel_在Mac OS X中用Docker部署GitLab
  7. keras版本 str object has no attribute decode
  8. 关于使用jquery修改hover伪标签的样式
  9. Android开发之APN网络切换
  10. python 数据结构转换层_python – 具有Maxpooling1D和channel_first的Keras模型
  11. 面试常考题目之atoi的实现
  12. JavaScript前端俄罗斯方块小游戏
  13. 新增本地存储功能 山石网科发布下一代防火墙新品
  14. stl中stacks的基本用法
  15. curl使用用户名密码
  16. AVR单片机特性简介
  17. zeppelin整合hive
  18. 2022年自考专业考试(英语)英语翻译练习题
  19. matlab unifit,【matlab】matlab在概率统计中的应用(二)
  20. 第八届蓝桥杯 java B组 日期问题

热门文章

  1. C++ Primer 5th笔记(chap 15 OOP)继承中的类作用域
  2. C++ Primer 5th笔记(8)chapter8 类:IO库-流的缓冲区
  3. 近世代数--群同构--第一同构定理
  4. 检索图书 FindMess.java
  5. MPICH 完整配置存档
  6. 计算机英语翻译的典故,中国成语典故英语翻译大全
  7. 变种GandCrab样本分析
  8. C++通过vmware.exe检测虚拟机
  9. 非MFC工程中使用MFC库
  10. MySQL WHERE:条件查询