垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象中哪些还“存活”,哪些已经“死去”。

引用的分类

Java将引用分为4种:

  • 强引用:指在程序代码之中普遍存在的引用赋值,即类似 “Object obj = new Object ()”
    这种引用关系。无论何种情况下,只要强引用关系存在,垃圾收集器就不会回收调被引用的对象。

  • 软引用:用来描述一些还有用,但非必须的对象。只要被软引用关联着的对象,在系统将要发生内存溢出异常之前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。

  • 弱引用:也是用来描述那些非必须对象,但它的强度比软引用还弱一些。被弱引用关联的对象只能生存到下一次垃圾收集发生为止

  • 虚引用:一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来获取一个对象实例。

引用计数法

在对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加一;当引用失效时,计数器值就减一;计数器为零的对象就是不可能再被使用的。
然而,在Java中,并没有选择引用计数法来进行内存管理。

可达性分析算法

可达性分析算法的基本思路就是通过一系列称为“GC Roots” 的根对象作为起始节点集,从这些节点开始根据引用关系向下搜索,搜索走过的路径称为“引用链”。如果某个对象到GC Roots 之间没有任何引用链,则证明该对象是不可能被使用的。


可作为GC Roots的对象如下:

  • 在虚拟机栈中引用的对象,比如各个线程被调用方法堆栈中的参数、局部变量、临时变量等
  • 在方法区中类静态属性引用的对象,比如引用类型静态变量
  • 在方法区中常量引用的对象,比如字符串常量池里的引用
  • 在本地方法栈中JNI(Native)引用的对象
  • Java虚拟机内部的引用,如基本数据类型对应的Class对象,常驻的异常对象
  • 所有被同步锁(synchronized)持有的对象
  • 反映虚拟机内部情况的JMXBean、JVMTI中注册的回调、本地代码缓存等

除了以上外,也可以"临时"加入一些对象作为GC Roots对象。(比如在新生代回收时,就需要考虑老年代对象的调用,需要将关联区域的对象也一并加入到GC Roots中)

死亡逃脱

先看以下代码

/*** 1.对象可以在被GC时自我拯救* 2.这种自救的机会只有一次,因为一个对象的finalize()方法最多只会被系统自动调用一次*/
public class FinalizeEscapeGC {public static FinalizeEscapeGC SAVE_HOOK = null;public void isAlive() {System.out.println("I am still alive !");}@Overrideprotected void finalize() throws Throwable {super.finalize();System.out.println("finalize method executed!");// 这里自救,重新建立关联FinalizeEscapeGC.SAVE_HOOK = this;}public static void main(String[] args) throws Throwable{SAVE_HOOK = new FinalizeEscapeGC();//对象第一次成功拯救自己SAVE_HOOK = null;System.gc();// 因为finalizer 方法优先级很低,暂停0.5秒,以等待它Thread.sleep(500);if (SAVE_HOOK != null) {SAVE_HOOK.isAlive();} else {System.out.println("I am dead!");}//下面这段代码与上面的完全相同,但是这次自救却失败了SAVE_HOOK = null;System.gc();// 因为finalizer 方法优先级很低,暂停0.5秒,以等待它Thread.sleep(500);if (SAVE_HOOK != null) {SAVE_HOOK.isAlive();} else {System.out.println("I am dead!");}}
}

执行结果:

这是为什么呢?
第一次成功自救是因为真正对一个对象回收,需要进行两次标记
如果对象在进行可达性分析后,发现没有引用链,那它将会被第一次标记,随后进行一次筛选,筛选的条件是是否有必要执行finalizer 方法,假如对象没有没有覆盖finalizer ()方法,或者finalizer ()已经被调用过,那虚拟机将这两种情况视为没必要执行。第二次不能逃脱,是因为系统已经执行过finalizer方法了
如果对象被判断为有必要执行finalizer()方法,那么该对象会被放进一个低优先级的队列F-Queue中,稍后收集器将对F-Queue中的对象进行第二次小规模的标记。第一次逃脱就是因为在finalizer方法中重新建立了关联,所以第二次标记时它被移出"即将回收" 的集合

finalizer方法运行代价高昂,不确定性大,无法保证各个对象的调用顺序,已经被官方声明为不推荐使用的语法。笔者建议大家使用try-finally方式

回收方法区

方法区的垃圾收集主要回收两部分内容: 废弃的常量和不再使用的类型

参考:《深入理解Java虚拟机》

Java如何决定对象的生死及对象该如何逃脱?相关推荐

  1. 一文看懂虚拟机中Java对象的生死判别

    j3_liuliang 通过上面两篇的介绍,相信大家已经知道虚拟机的内存布局和对象创建的过程及在虚拟机中的分布的,那么一个对象创建出来是不可能永生的总会有死亡的时候而虚拟机是如何判定一个对象的生死那就 ...

  2. contentwindow无法搜索对象_面试官:讲一下Jvm中如何判断对象的生死?

    但凡问到 JVM(Java 虚拟机)通常有 99% 的概率一定会问,在 JVM 中如何判断一个对象的生死状态? 判断对象的生死状态的算法有以下几个: 1.引用计数器算法 引用计算器判断对象是否存活的算 ...

  3. 面试官:讲一下Jvm中如何判断对象的生死?

    但凡问到 JVM(Java 虚拟机)通常有 99% 的概率一定会问,在 JVM 中如何判断一个对象的生死状态? 判断对象的生死状态的算法有以下几个: 1.引用计数器算法 引用计算器判断对象是否存活的算 ...

  4. JVM(三)对象的生死判定和算法详解

    好的文章是能把各个知识点,通过逻辑关系串连起来,让人豁然开朗的同时又记忆深刻. 导读:对象除了生死之外,还有其他状态吗?对象真正的死亡,难道只经历一次简单的判定?如何在垂死的边缘"拯救&qu ...

  5. Jvm中如何判断对象的生死?

    但凡问到 JVM(Java 虚拟机)通常有 99% 的概率一定会问,在 JVM 中如何判断一个对象的生死状态? 判断对象的生死状态的算法有以下几个: 1.引用计数器算法 引用计算器判断对象是否存活的算 ...

  6. java查看对象锁级别_对象级别锁 vs 类级别锁(Java)

    前言 对于多线程(并发)和Spring Boot这两块在同步进行学习中,在看到使用synchronized关键字使操作同步时,看到和C#中不一样的东西,所以这里呢,就深入学习了下,若有错误之处,还望指 ...

  7. java对象的访问定位_2、JVM-Java对象的创建、对象结构、对象访问定位-Go语言中文社区...

    目录 记录下来方便个人学习复习 注:根据new的参数在常量池中定位一个类的符号引用 --这句话的意思是:常量池相当于c语言中的指针地址集合,所以就是在常量池中保存new对象的地址,通过地址定位对象在堆 ...

  8. Java通过泛型的模板类型实例化对象

    Java通过泛型的模板类型实例化对象 最近自己研究了下mvvm框架,使用泛型的方式可节省很多代码,并且可以合并很多冗余代码,为了最大化的精简代码想到了通过泛型的type用反射的方式实例化对象,这样对象 ...

  9. JAVA编程思想学习笔记——第一章 对象导论

    搞了一年多java,野路子出身,发现java基础这块还是相当的薄弱!故决定学习<Java编程思想>这本书.在此把学习的知识点记录下! 面向对象的五大特性 1.万物皆为对象 2.程序是对象的 ...

最新文章

  1. 云计算灾备原理与预防恢复方案
  2. android app数据库数据存放
  3. 函数 —— strtok() 例如:按照字符拆分字符串,放入新定义的数组中;按照字符拆分字符串,放入原先的数组中
  4. 有三AI正式跨入2.0,诚邀参与内容创作以及广告须知
  5. Impala介绍,Impala架构,Impala安装,impala Shell ,分区创建,refresh,load数据,获取数据的元数据
  6. 基于HLS格式的低延时互动直播技术
  7. .NET Nancy 详解(三) Respone 和 ViewEngine
  8. Scala IDE for Eclipse的下载、安装和WordCount的初步使用(本地模式和集群模式)
  9. C++ 拷贝构造函数
  10. 记录一次nginx 配置https 强制http转发到https
  11. 盒子浮动的重要性及对其它元素的影响
  12. easypanel安装php5.4,kangle一键脚本-凌梦云
  13. 有效预防xss_4类防御XSS的有效方法
  14. 服务器的mib文件,snmp 服务器增加 mib
  15. C语言:int转char
  16. Zabbix - 微信报警
  17. Windows下设置桌面壁纸的代码(QT版)
  18. ORB-SLAM3 IMU(李群)+Frame+KeyFrame+MapPoint
  19. mysql 数据精确度,MySQL中数值类型的精度探析
  20. 7-29 王小二分饼

热门文章

  1. cacti数据库修复命令
  2. 高通SDM660芯片的启动流程
  3. iPad Pro 2022款将迎来大改款 支持反向无线充电
  4. 上门洗车公司应该如何经营?
  5. html div圆滑效果,Html-Css-设置DIV边框圆滑
  6. 1700打印机恢复出厂设置步骤
  7. 广西计算机一级机试题,全国高校计算机等级考试(广西考区)一级机试试题(C)
  8. 推送V2 - 开发笔记整理
  9. web前端设计与开发——HTML基础(六)标签(四)div、ul、ol、table、tr、td、th(有标签中文意思)
  10. 微信消息防撤回 + 智能聊天机器 Python itchat实现