微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

【JVM笔记】GC:判断对象是否存活

概述:

判断对象是否存活(或是否死去):可达性分析算法

概念介绍:引用、两次标记

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

【引用计数算法】

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

JVM没有采用,因为引用计数算法很难解决循环引用问题

class OBJ:
    Object instance;
    test():
      objA=new OBJ();
      objB=new OBJ();
      objA.instance=objB,objB.instance=objA

objA和objB相互引用对方,导致它们的引用计数不为0,无法回收。

【可达性分析算法】

通过一系列称为"GC Roots"的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索搜索过程所走过的路径称为“引用链”,如果某个对象到GC Roots间没有任何引用链相连,即GC Roots到这个对象不可达,此对象不能再被使用。

在java中,固定作为GC Roots的对象包括

虚拟机栈中引用的对象

方法区中类静态属性引用的对象

方法区中常量引用的对象,如字符串常量池里 的引用

本地方法栈(native方法)引用的对象

Java虚拟机内部的引用,如基本数据类型对应的class对象,一些常驻的异常对象。

所有被同步锁持有的对象

反映Java虚拟机内部情况的JMXBean?jvmti注册的回调,本地代码缓存等

 还可以有其他对象临时加入,共同构成GC Roots 集合,比如分代收集和局部回收时,一个区域的对象可能被其他区域的对象引用,这时候需要将这些关联区域的对象也一并加入GCRoots 集合中。

【引用】

如果引用类型的数据中存储的数值代表另外一块内存的起始地址,就称为是代表一个引用。

在JDK1.2之后,java将引用分为强引用,软应用,弱引用,虚引用

强引用:传统的引用定义。  无论任何情况下,只要强引用存在垃圾收集器就不会回收掉被引用的对象

软引用:描述一些还有用但非必要的对象。

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

弱引用描述那些非必须对象,但是它的强度比软引用更弱一些。被弱引用关联的对象只能生存到下一次垃圾收集发送为止。当垃圾收集器开始工作无论当前内存是否足够都会回收弱引用的对象

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

【对象宣告死亡的过程】经过两次标记

【两次标记过程】

(1)是否不可达:是否有GCRoots到对象的引用链。

(2)是否有必要执行finalize()方法,如果没有直接回收。

没有必要执行: 对象没有覆盖finalize()方法 或 finalize()方法已经被虚拟机调用

如果有必要执行finalize()方法,那么该对象会被放置在一个名为F-Queue的队列中,并在稍后一条由虚拟机自动建立的,低调度优先级的Finalizer线程去执行finalize()方法

收集器会在F-Queue中的对象做第二次标记,如果对象在finalize()中拯救自己,即与引用链上的任意一个对象建立关联即可。

并不鼓励使用finalize()拯救对象,运行代价高昂,不确定性大。

原文地址:https://www.jb51.cc/wenti/3286968.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐