-
2016-11-01 09:50:32
java对象存活判断
1.判断对象是否存活的算法
1.1引用计数算法
为每一个对象设置一个对象引用计算器,每当有地方引用到该对象的时候,该对象的引用计算器就自动的加一,如果每当引用失效的时候,该对象的引用计算器就会相应的减一。任何时刻当该对象的引用计数器为0的时候就说明了该对象不再被引用。
1.1.1引用计算算法的缺点
当objA和objB相互引用的时候,他们的引用计数器都是1,他们相互引用着对方,但是实际上这两个对象已经不能被访问,于是引用计数器无法通知系统区回收他们。
objA.instance = objB; objB.instance = objA;
1.2可达性分析算法
这个算法的基本思想是通过一个根节点RootGC作为一个起始点,从这个节点往下搜索,搜索所走过的路径就是引用链(Reference Chain),当一个对象到RootGC都没有引用链的时候(图论说法就是当一个GCRoot节点到该对象不可达),则证明此对象是不可用的。
1.2.1 java中可以用作GC Root的对象
1.虚拟机栈中引用的对象
2.方法区中静态属性引用的对象
3.方法区中常量引用的对象
4.本地方法栈JNI(即一般说的Native方法)引用的对象
1.2.2 gc自我拯救
当通过系统分析发现,RootGC节点到该对象不可达的时候,是否对象就会被回收的呢,答案不是一定的,这时候他暂时时处于缓刑阶段,至少要经过两次的标记的过程,才真正宣告一个对象的死亡,第一次是当系统检测到该对象到RootGC节点不可达的时候,进行第一次的标记,然后系统就会检查该对象有没有覆盖finalize方法,如果有的话便会执行finalize方法,如果该对象在finalize方法中与任何一个对象进行关联的话便可以不会被回收。
2. 回收方法区
java虚拟机规范中确实规定了虚拟机中在方法区是不会实现垃圾回收的,而且在方法区中实现垃圾回收性价比比较低,在堆中,特别是新生代,一般垃圾回收可以回收70-80%的空间,但是永生代中的效率远低于这个。
2.1 永生代的垃圾回收包括两部分的内容
1 废弃常量
2 无用的类
2.2无用的类的定义:
必须满足3个条件:
1.该类的所有实例都已经被回收,也就是Java堆中不存在这个类的实例。
2.加载该类的ClassLoader也已经被回收。
3.该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问这个类。
更多相关内容 -
深入理解Java虚拟机——判断对象是否存活
2022-02-11 19:46:47目录一、判断对象是否存活的方式二、引用计数法2.1、引用计数法的概述2.2、引用计数法的缺点2.3、查看对象是否被回收掉三、可达性分析3.1、可达性分析的概述3.2、GC Roots的对象的概述 一、判断对象是否存活的方式 ...一、判断对象是否存活的方式
- 引用计数法
- 可达性分析
二、引用计数法
2.1、引用计数法的概述
- 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1; 任何时刻计数器为0的对象就是不可能再被使用的。
2.2、引用计数法的缺点
- 至少主流的java虚拟机里面没有选用引用计数算法来管理内存。其中最主要的原因是它很难解决对象之间相互循环引用的问题。
2.3、查看对象是否被回收掉
- 添加如下2个参数:
- -verbose:gc
- -xx:+PrintGCDetail
三、可达性分析
3.1、可达性分析的概述
- 通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Renfence Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。
3.2、GC Roots的对象的概述
- 在java语言中,可作为GC Roots的对象包括下面几种:
- 虚拟机(栈帧中的本地变量表)中引用的对象。
- 方法区中类静态属性引用的对象。
- 方法区中常量引用的对象。
- 本地方法栈中JNI(即一般说的Native方法)引用对象。
-
JVM:判断一个Java对象是否存活
2021-03-17 17:37:20前言如何判断一个Java对象是否存活对于垃圾回收、防止内存泄漏等十分重要本文将全面讲解判断Java对象存活的方式,希望你们会喜欢在接下来的日子,我会推出一系列讲解JVM的文章,具体如下;感兴趣可持续关注Carson_Ho...前言
如何判断一个Java对象是否存活对于垃圾回收、防止内存泄漏等十分重要
本文将全面讲解判断Java对象存活的方式,希望你们会喜欢
在接下来的日子,我会推出一系列讲解JVM的文章,具体如下;感兴趣可持续关注Carson_Ho的安卓开发笔记
示意图
目录
示意图
1. 判断方式
垃圾收集器对 Java堆里的对象 是否进行回收的判断准则:Java对象是存活 or 死亡
判断对象为死亡才会进行回收
在Java虚拟机中,判断对象是否存活有2种方法:
引用计数法
引用链法(可达性分析法)
下面会进行详细介绍。
2. 引用计数法
2.1 方式描述
给 Java 对象添加一个引用计数器
每当有一个地方引用它时,计数器 +1;引用失效则 -1;
2.2 判断对象存活准则
当计数器不为 0 时,判断该对象存活;否则判断为死亡(计数器 = 0)。
2.3 优点
实现简单
判断高效
2.4 缺点
无法解决 对象间相互循环引用 的问题
即该算法存在判断逻辑的漏洞
具体描述
// 对象objA 和 objB 都有字段 name
// 两个对象相互进行引用,除此之外这两个人对象没有任何引用
objA.name = objB;
objB.name = objA;
// 实际上这两个对象已经不可能再被访问,应该要被垃圾收集器进行回收
// 但因为他们相互引用,所以导致计数器不为0,这导致引用计数算法无法通知垃圾收集器回收该两个对象
正由于该算法存在判断逻辑漏洞,所以 Java虚拟机没有采用该算法判断Java是否存活。
3. 引用链法(可达性分析法)
很多主流商用语言(如Java、C#)都采用 引用链法 判断 Java对象是否存活。
含3个步骤:
可达性分析
第一次标记 & 筛选
第二次标记 & 筛选
3.1 可达性分析
a. 方式描述
将一系列的 GC Roots 对象作为起点,从这些起点开始向下搜索。
可作为 GC Root 的对象有:
1.Java虚拟机栈(栈帧的本地变量表)中引用的对象
2.本地方法栈 中 JNI引用对象
3.方法区 中常量、类静态属性引用的对象
向下搜索的路径 = 引用链
如下图:
示意图
b. 判断 对象是否可达 标准
当一个对象到 GC Roots 没有任何引用链相连时,则判断该对象不可达
没有任何引用链相连 = GC Root到对象不可达 = 对象不可用
示意图
特别注意
可达性分析 仅仅只是判断对象是否可达,但还不足以判断对象是否存活 / 死亡
当在 可达性分析 中判断不可达的对象,只是“被判刑” = 还没真正死亡
不可达对象会被放在”即将回收“的集合里。
要判断一个对象真正死亡,还需要经历两个阶段:
第一次标记 & 筛选
第二次标记 & 筛选
3.2 第一次标记 & 筛选
对象 在 可达性分析中 被判断为不可达后,会被第一次标记 & 准备被筛选
a. 不筛选:继续留在 ”即将回收“的集合里,等待回收;
b. 筛选:从 ”即将回收“的集合取出
筛选的标准:该对象是否有必要执行 finalize()方法
若有必要执行(人为设置),则筛选出来,进入下一阶段(第二次标记 & 筛选);
若没必要执行,判断该对象死亡,不筛选 并等待回收
当对象无 finalize()方法 或 finalize()已被虚拟机调用过,则视为“没必要执行”
3.3 第二次标记 & 筛选
当对象经过了第一次的标记 & 筛选,会被进行第二次标记 & 准备被进行 筛选
a. 方式描述
该对象会被放到一个 F-Queue 队列中,并由 虚拟机自动建立、优先级低的Finalizer 线程去执行 队列中该对象的finalize()
finalize()只会被执行一次
但并不承诺等待finalize()运行结束。这是为了防止 finalize()执行缓慢 / 停止 使得 F-Queue队列其他对象永久等待。
b. 筛选标准
在执行finalize()过程中,若对象依然没与引用链上的GC Roots 直接关联 或 间接关联(即关联上与GC Roots 关联的对象),那么该对象将被判断死亡,不筛选(留在”即将回收“集合里) 并 等待回收
3.4 总结
3步骤 + 以下流程
示意图
4. 总结
本文全面讲解判断Java对象存活的方式
在接下来的日子,我会推出一系列讲解JVM的文章,具体如下;感兴趣的同学可以继续关注本人运营的Wechat Public Account:
示意图
请点赞!因为你的鼓励是我写作的最大动力!
不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度。
-
java对象存活分析
2018-03-04 14:14:05java虚拟机总共分为五个区域,其中三个是线程私有:程序计数器,虚拟机栈,本地方法栈,两个是线程共享:堆,...java堆和方法区主要存放各种类型的对象(方法区中也存储一些静态变量和全局常量等信息),那么我们...java虚拟机总共分为五个区域,其中三个是线程私有:程序计数器,虚拟机栈,本地方法栈,两个是线程共享:堆,方法区。线程私有的区域等到线程结束时(栈帧出栈时)会自动被释放,空间比较容易清理。而线程共享的java堆和方法区中的空间较大而且没有线程的回收容易产生很多垃圾信息,GC垃圾回收真正关心的就是这部分。
java堆和方法区主要存放各种类型的对象(方法区中也存储一些静态变量和全局常量等信息),那么我们在使用GC对其进行回收的时候首先要考虑的就是如何判断一个对象是否应该被回收。也就是要判断一个对象是否还有其他的引用或关联使得这个对象处于存活的状态。我们需要将不在存活状态的所有对象标记出,以便于GC进行回收。
判断对象是否存活有两种比较常见的方法:引用计数法与可达性分析算法。
引用计数法
引用计数法的逻辑非常简单,但是存在问题,java并不采用这种方式进行对象存活判断。
引用计数法的逻辑是:在堆中存储对象时,在对象头处维护一个counter计数器,如果一个对象增加了一个引用与之相连,则将counter++。如果一个引用关系失效则counter–。如果一个对象的counter变为0,则说明该对象已经被废弃,不处于存活状态。
这种方法来标记对象的状态会存在很多问题:
1 jdk从1.2开始增加了多种引用方式:软引用、弱引用、虚引用,且在不同引用情况下程序应进行不同的操作。如果我们只采用一个引用计数法来计数无法准确的区分这么多种引用的情况。
引用计数法无法解决多种类型引用的问题。但这并不是致命的,因为我们可以通过增加逻辑区分四种引用情况,虽然麻烦一些但还算是引用计数法的变体,真正让引用计数法彻底报废的下面的情况。
2 如果一个对象A持有对象B,而对象B也持有一个对象A,那发生了类似操作系统中死锁的循环持有,这种情况下A与B的counter恒大于1,会使得GC永远无法回收这两个对象。
可达性分析算法
在主流的商用程序语言中(Java和C#),都是使用可达性分析算法判断对象是否存活的。这个算法的基本思路就是通过一系列名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,下图对象object5, object6, object7虽然有互相判断,但它们到GC Roots是不可达的,所以它们将会判定为是可回收对象。
那么那些点可以作为GC Roots呢?一般来说,如下情况的对象可以作为GC Roots:
- 虚拟机栈(栈桢中的本地变量表)中的引用的对象
- 方法区中的类静态属性引用的对象
- 方法区中的常量引用的对象
- 本地方法栈中JNI(Native方法)的引用的对象
HotSpot虚拟机如何实现可达性算法?
java中的主流虚拟机HotSpot采用可达性分析算法来确定一个对象的状态,那么HotSpot在具体实现该算法时采用了哪些结构?
使用OopMap记录并枚举根节点
HotSpot首先需要枚举所有的GC Roots根节点,虚拟机栈的空间不大,遍历一次的时间或许可以接受,但是方法区的空间很可能就有数百兆,遍历一次需要很久。更加关键的是,当我们遍历所有GC Roots根节点时,我们需要暂停所有用户线程,因为我们需要一个此时此刻的”虚拟机快照”,如果我们不暂停用户线程,那么虚拟机仍处于运行状态,我们无法确保能够正确遍历所有的根节点。所以此时的时间开销过大更是我们不能接受的。
基于这种情况,HotSpot实现了一种叫做OopMap的数据结构,这种数据结构在类加载完成时把对象内的偏移量是什么类型计算出,并且存放下位置,当需要遍历根结点时访问所有OopMap即可。
用安全点Safepoint约束根节点
如果将每个符合GC Roots条件的对象都存放进入OopMap中,那么OopMap也会变得很大,而且其中很多对象很可能会发生一些变化,这些变化使得维护这个映射表很困难。实际上,HotSpot并没有为每一个对象都创建OopMap,只在特定的位置上创建了这些信息,这些位置称为安全点(Safepoints)。
为了保证虚拟机中安全点的个数不算太多也不是太少,主要决定安全点是否被建立的因素是时间。当进行了耗时的操作时,比如方法调用、循环跳转等时会产生安全点。此外,HotSpot虚拟机在安全点的基础上还增加了安全区域的概念,安全区域是安全点的扩展。在一段安全区域中能够实现安全点不能达成的效果。
转自:http://blog.csdn.net/quinnnorris/article/details/75040538
-
Java虚拟机判断对象实例是否存活?
2022-04-01 17:14:28在堆里面存放着Java世界中几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”(即不可能再被任何途径使用的对象)。 1.引用计数算法 很多教科... -
JVM 如何判断一个Java对象是否存活
2020-02-15 11:34:16给java对象添加一个引用计数指针,每当有一个地方引用它时 计数+1引用失效则计数-1 当计数器不为0时候 alive 为0 dead 优点:实现简单 判断高效 缺点:无法判断对象间相互循环引用的问题 二 引用链法... -
java如何判断一个对象是否存活
2020-03-26 19:19:08引用计数器法:每个对象设置一个引用计数器,当对象被引用,计算器加1,当引用失效,计算器减一。当计数器为0时, 表示引用失效,也就是"死对象",可以被垃圾回收机制回收。 缺陷:无法解决循环依赖的问题。有两个... -
JAVA如何判断一个对象是否存活
2021-03-23 08:15:17JAVA判断一个对象是否存活有两种方法:1. 引用计数法所谓引用计数法就是给每一个对象设置一个引用计数器,每当有一 个地方引用这个对象时,就将计数器加一,引用失效时,计数器就 减一。当一个对象的引用计数器为... -
JVM:判断对象是否存活
2022-03-25 11:54:30JVM如何判断对象是否存活 -
Java判断对象是否存活
2018-06-24 17:55:191、引用计数算法在对象中...注:在java虚拟机里面没有选用引用计数算法来管理内存的,主要是因为它无法解决对象之间的相互循环引用问题。例如:Object obj = null;public void t(){ Test t1 = new Test();... -
JVM系列第三篇:判断一个Java对象是否存活
2020-03-25 18:05:12本文将全面讲解判断Java对象存活的方式,希望你们会喜欢 目录 1. 判断方式 垃圾收集器对 Java堆里的对象 是否进行回收的判断准则:Java对象是存活 or 死亡 判断对象为死亡才会进行回收 在Java虚拟机中... -
JVM如何判断一个Java对象是否存活
2019-09-19 20:02:101.为什么要判断一个Java对象是否存活 判断一个Java对象是否存活对于垃圾回收、防止内存泄漏等十分重要 垃圾收集器对Java堆里的对象 ,判断对象为死亡才会进行回收 在Java虚拟机中,判断对象是否存活有2种方法: ... -
如何判断一个Java对象是否存活?
2019-10-23 22:56:53这是因为判断一个Java对象是否存活对于垃圾回收、防止内存泄漏等十分重要,垃圾收集器对 Java堆里的对象是否存活进行判断,Java对象存活不回收,死亡则回收。 判断方式:  ... -
如何判断对象是否存活
2020-08-23 18:41:48判断对象是否存活的方法主要有两种:引用计数算法,可达性分析算法 引用计数算法 给对象添加一个引用计数器,当有一个地方引用它时,引用计数器+1,当有一个引用失效时,引用计数器-1,引用计数器为0时,表示对象不... -
Java对象是否存活的判断机制
2020-11-23 18:46:431.为什么要判断一个Java对象是否存活 判断一个Java对象是否存活对于垃圾回收、防止内存泄漏等十分重要 垃圾收集器对 Java堆里的对象 ,判断对象为死亡才会进行回收 在Java虚拟机中,判断对象是否存活有2种方法: ... -
java判断一个对象是否存活
2019-03-06 23:39:25原理:给java对象添加一个引用计数器,当被引用一次+1,引用失效-1,当计数器为0时则判定该对象死亡 缺点:遇见两个对象相互引用的情况则失效 2.引用链法(可达性分析法) 步骤: <1.可达性分析 ... -
判断Java对象是否存活的方法
2016-11-06 16:59:17JVM高级特性与最佳实践》堆中几乎存放着Java世界中所有的对象实例,垃圾收集器在对堆回收之前,第一件事情就是要确定这些对象哪些还“存活”着,哪些对象已经“死去”(即不可能再被任何途径使用的对象),哪用什么... -
JVM中判断对象是否存活的方法
2016-10-24 15:51:16Java中几乎所有的对象实例都存放在堆中,在垃圾收集器对堆内存进行回收前,第一件事情就是要确定哪些对象还“存活”,哪些对象已经“死去”(即不可能再通过任何途径被使用)。引用计数算法 首先需要声明,至少主流... -
JVM如何判断Java对象是否存活,是否要被GC回收?
2020-02-02 00:11:23GC在对堆内存进行垃圾清理之前,需要判断哪些Java对象不再被使用,需要被回收。通常有两种算法:引用计数算法、可达性分析算法。 引用计数算法(已被淘汰) 引用计数算法:在对象中添加一个引用计数器,每当有一个... -
Java垃圾回收(一)对象存活状态判断---深入理解Java虚拟机
2016-07-25 23:00:53首先我们先来看下垃圾回收中不会管理到的内存区域,在Java虚拟机的运行时数据区我们可以看到,程序计数器,虚拟机栈,本地方法栈这三个地方是比较特别的。这个三个部分的特点就是线程私有的,它们随着线程的创建而... -
深入理解Java虚拟机之判断对象是否存活
2017-11-28 21:59:50深入理解Java虚拟机之判断对象是否存活 我们知道Java虚拟机中对象的存储位置在堆上,所以GC回收主要也就是在堆上进行的,那么垃圾收集器在进行对象回收的时候肯定不能随便收集,必须要判断对象的状态是不是可以被... -
Carson带你学JVM:Java对象如何判断存活原则-引用计数法 & 引用链法
2019-10-14 08:05:44本文将全面讲解判断Java对象存活的方式,希望你们会喜欢 -
判断Java中对象存活的算法以及Java中存在的几种引用
2017-04-01 11:23:43判断Java中对象存活的算法:(1)引用计数算法:给对象中添加一个引用计数器,每当一个地方引用它的时候就将计数器加1,当引用失效的时候就将计数器减一;任何时刻计数器为0的对象都是不可能在被使用的。这中方法的... -
java 对象存活分析——引用计数法&可达性分析(转)
2018-08-06 11:06:00java 对象存活分析——引用计数法&可达性分析 地址:https://blog.csdn.net/quinnnorris/article/details/75040538 java虚拟机总共分为五个区域,其中三个是线程私有:程序计数器,虚拟机栈,本地方法栈,... -
面试官:如何判定一个对象是否存活?
2021-11-21 12:32:59 在进行垃圾回收之前,第一件要做的事情就是要判断哪些对象还存活着,以便于回收非存活状态的对象。那如何去判断一个对象是否存活呢? 本文带领大家深入探究两种算法,再也不需要应付面试了,深入了解底层逻辑... -
简单检测java服务是否存活,如果没有存活,启动服务的工具
2022-04-18 14:40:05import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; /** * @author :Fan * @date :Created in 2022/4/18 14:18 * @description: * @modified By: */ public class ... -
java中对象的引用类型及判断对象是否存活的算法
2016-08-19 10:27:45堆中几乎存放着Java世界中所有的对象实例,垃圾收集器在对堆回收之前,第一件事情就是要确定这些对象哪些还“存活”着,哪些对象已经“死去”(即不可能再被任何途径使用的对象) 1.引用计数算法 很多教科书判断...