在堆中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事就是要确定这些对象之中哪些还活着,哪些对象已经死去.
判断对象是否已经死亡有以下几种算法:
  1. 引用计数法算法
定义 : 给对象中添加一个引用计数器,当有一个地方引用时,计数器加1,引用失效时,就减1,当对象的引用计数器为0时,对象就是不可再被使用的.
特点 : JAVA虚拟机中很少使用这种算法,主要原因是它很难解决对象之间的循环引用问题
  1. 可达性分析算法
定义 : 通过一系列的称为 GC Roots 的对象作为起点,从这些节点开始向下搜索,搜索把走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连(就是从GC Roots 到这个对象不可达)时,则证明此对象是不可用的.如下图
 
上图中的 5,6,7 对象就是不可达的,就是不可用的.
 
1) 哪些对象可以作为 GC Roots 对象呢?
1 虚拟机栈(栈帧中的本地变量表)中引用的对象
2 方法区中类静态属性引用的对象
3 方法区中常量引用的对象
4 本地方法栈中JNI引用的对象
 
 
2) 再谈引用:(从上到下依次减弱)
1 强引用 : 只要强引用还存在,垃圾收集器永远不回收被引用的对象
2 软引用 : 在内存溢出异常之前,回收对象
3 弱引用 : 在下一次 GC 时,无论当前内存是否足够,都会回收被引用的对象
4 虚引用 : 没用,唯一的用处是在对象回收时,会收到一个系统通知
 
 
3) 对象的 finalize() 方法作用
生存还是死亡?
即使在可达性分析算法中不可达的对象,也并非是"非死不可"的,这时候它们暂时处于"缓刑"阶段,要真正宣告一个对象死亡,至少要经历2次标记:
1 如果对象在进行可达性分析后发现对象不可达,那它将会被第一次标记并进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法.当对象没有覆盖finalize()方法,或者finalize()方法已经执行过,虚拟机将这种情况视为没有必要执行
 
2 如果对象被判定为有必要执行finalize()方法,那么这个对象将会放置在一个叫做F-Queue的队列之中,并在稍后由一个由虚拟机自动建立的,低优先级的Finalizer线程去执行它.这里所谓的招行是指虚拟机会触发这个方法,但并不承诺等待它运行结束,这样做的原因是,如果一个对象在finalize()方法中做耗时的操作,将很可能会导致 F-Queue队列中的其它对象永久处于等待,甚至导致整个内存回收系统线程崩溃, finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次标记,如果对象要在finalize()中成功拯救自己,即只要对象重新和引用链上的任何一个对象发生关联即可,即将自己(this关键字)赋值给某个类变量或者对象的成员变量,那么在第二次标记时它将被移出"即将回收"的集合,如果对象这时候还没有逃脱,那么基本上它真的要被回收了
注:尽量不要用finalize()方法,忘了这个方法
 

4 Java 如何判定是否存活或者死亡的更多相关文章

  1. Java虚拟机判定对象存活算法

    1.引用计数算法 描述:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器值为0的对象就是不可能再被使用的. 特点:实现简单,判定效率高. ...

  2. 深入Java虚拟机--判断对象存活状态

    程序计数器,虚拟机栈和本地方法栈 首先我们先来看下垃圾回收中不会管理到的内存区域,在Java虚拟机的运行时数据区我们可以看到,程序计数器,虚拟机栈,本地方法栈这三个地方是比较特别的.这个三个部分的特点 ...

  3. JVM-对象的存活与死亡

    当Java虚拟机进行垃圾收集的时候,那么它必须要先判断对象,是否还存活,如果存活就不能对它进行回收.所以判断一个对象是否存活是Java虚拟机必须要实现的. 1.对象是否存活 1)引用计数器:给对象添加 ...

  4. java实现判定新旧版本号

    废话不多说,直接上代码 /** * 判断是否为最新版本方法 将版本号根据.切分为int数组 比较 * * @param localVersion 本地版本号 * @param onlineVersio ...

  5. Android 内存泄漏分析与解决方法

    在分析Android内存泄漏之前,先了解一下JAVA的一些知识 1. JAVA中的对象的创建 使用new指令生成对象时,堆内存将会为此开辟一份空间存放该对象 垃圾回收器回收非存活的对象,并释放对应的内 ...

  6. Java虚拟机学习笔记(二)--- 判断对象是否存活

    Java堆中存放着所有的对象实例,垃圾收集器在堆进行回收之前,需要判断对象是“存活”还是“死亡”(即不可能再被任何途径引用的对象). 最常见的一种判断对象是否存活算法是引用计数算法, 给对象加一个引用 ...

  7. Java 垃圾回收算法

    在之前Java 运行期数据区一文中,介绍了运行时内存的各个部分.其中程序计数器.虚拟机栈.本地方法栈都随线程消亡,所以,这几个区域的内存分配和回收都具备确定性.而 Java 堆和方法区不同,我们只有在 ...

  8. 《深入理解Java虚拟机》读书笔记2--垃圾回收

    回收哪些内存/对象 引用计数算法 可达性分析算法 finalize()方法 HotSpot实现分析 转载:http://blog.csdn.net/tjiyu/article/details/5398 ...

  9. Java基础(面试题)

    1:面向对象编程有很多重要的特性: 封装,继承,多态和抽象. 2:什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? (1)Java虚拟机是一个可以执行Java字节码的虚拟机进程.J ...

随机推荐

  1. JAVA中json转换为集合(对象)之间的相互转换

    字符串转换为json对象: String strResult = RestUtil.getRestContent(url+"/service/peccancy/myOrderList&quo ...

  2. ArcEngine读取ShapeFile时,出现乱码的解决方案

    ArcEngine读取ShapeFile时,如果用LicenseControl的话,字段中含有汉字时可以正常使用,当使用LicenseInitializer进行初始化时,读取含有汉字的字段时,就会出现 ...

  3. Meteor环境安装配置

    在本教程中,我们将展示如何在windows操作系统安装Meteor .在我们开始学习使用Meteor 之前,我们将需要NodeJS.如果你还没有安装它,则可以点击下表中的链接. 必须条件 Meteor ...

  4. CentOS 6.x ELK(Elasticsearch+Logstash+Kibana)

    CentOS 6.x ELK(Elasticsearch+Logstash+Kibana) 前言 Elasticsearch + Logstash + Kibana(ELK)是一套开源的日志管理方案, ...

  5. android多个fragment返回键层层返回

    在FragmentActivity的fragment跳转的时候加入到执行栈. public void switchFrag(BaseFragment to) { getSupportFragmentM ...

  6. SQL 快速参考

    SQL 快速参考 SQL 语句 语法 AND / OR SELECT column_name(s)FROM table_nameWHERE conditionAND|OR condition ALTE ...

  7. Windows 上通过本地搭建 Jekyll环境

    一 准备Ruby环境 1 我们首先须要安装Ruby.从站点下载Ruby 上下载Ruby最新版和对应的DevKit. 我下载的是Ruby 2.1.4 (x64)和DevKit-mingw64-6 .注意 ...

  8. HDU 5303 Delicious Apples (贪心 枚举 好题)

    Delicious Apples Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Other ...

  9. 【Android数据存储】- File

    个人学习整理.如有不足之处,请不吝不吝赐教. 转载请注明:@CSU-Max 读写本应用程序数据目录中的文件        此种方法读写的文件在/data/data/<应用程序包名>中   ...

  10. [转] 买彩票的利器--gun

    源链接 还在自己买彩票吗,有个现成的:GNU shuf命令. shuf -i - -n | 这样就会产生两组彩票(1~36个数字任选) 当然还可以派其他用途,比如: shuf -e clubs hea ...