.net 把一个对象赋值给一个参数_Java GC回收算法-判定一个对象是否可以回收

afb5f03ac48ae692d2440650e6a07c1d.png

开源推荐

推荐一款一站式性能监控工具(开源项目)

Pepper-Metrics是跟一位同事一起开发的开源组件,主要功能是通过比较轻量的方式与常用开源组件(jedis/mybatis/motan/dubbo/servlet)集成,收集并计算metrics,并支持输出到日志及转换成多种时序数据库兼容数据格式,配套的grafana dashboard友好的进行展示。项目当中原理文档齐全,且全部基于SPI设计的可扩展式架构,方便的开发新插件。另有一个基于docker-compose的独立demo项目可以快速启动一套demo示例查看效果https://github.com/zrbcool/pepper-metrics-demo。如果大家觉得有用的话,麻烦给个star,也欢迎大家参与开发,谢谢:)


进入正题...

GC的出现解放了程序员需要手动回收内存的苦恼,但我们也是要了解GC的,知己知彼,百战不殆嘛。

常见的GC回收算法主要包括引用计数算法、可达性分析法、标记清除算法、复制算法、标记压缩算法、分代算法以及分区算法。

其中,引用计数法和可达性分析法用于判定一个对象是否可以回收,其他的算法为具体执行GC时的算法。

今天来聊聊可达性分析法,并说明一下什么样的对象才是真正可以被回收的。

在介绍引用计数法的时候,我们提到了此种算法的循环引用的缺陷,所以Java没有使用此种算法。

那Java使用的是啥算法来标记一个对象是否是垃圾对象呢?

Java是通过判断一个对象是否可触及,以及一个对象的引用类型(强引用、软引用、弱引用、虚引用)来决定是否回收这个对象。

本文将根据上述,分为两部分进行介绍。

最后会简单介绍一下GC回收过程中保证数据一致性的方法:Stop the World

1 如何判断一个对象是否可触及?

判断是否可触及包含两个要素: 通过可达性分析该对象到GC Root不可达,如果不可达会进行第一次标记。 已经丧失"自救"机会,如果没有自救机会,会进行第二次标记,此时该对象可回收。

1.1 可达性分析

可达性分析法定义了一系列称为"GC Roots"的对象作为起始点,从这个起点开始向下搜索,每一条可达路径称为引用链,当一个对象没有任意一条引用链可以到达"GC Roots"时,那么就对这个对象进行第一次"可回收"标记。

那么什么是GC Root呢?

可以理解为由堆外指向堆内的引用。

那么都有哪些对象可以作为GC Roots呢? 包括如下几种 代码中某一方法中的局部变量 类变量(静态变量) 常量 本地方法栈中引用的对象 * 已启动且未停止的线程

下面以一段代码来简单说明一下前三类

class 

这段代码的运行时内存图示如下:

5e60f187f146687b19c2cbc780c415c6.png

首先,类加载器加载Test类,会初始化静态变量a,将常量引用指向常量池中的字符串,完成Test类的加载;

然后,main方法执行,main方法会入虚拟机方法栈,执行main方法会在堆中创建A的对象,并赋值给局部变量innerA。

此时GC Roots状态如下:

b624f4b2dac7061ffcb1da43777ea130.png

当main方法执行完出栈后,变为:

aaa29b059de5d707e9f62895bf66f7fa.png

第三个对象已经没有引用链可达GC Root,此时,第三个对象被第一次标记。

1.2 对象的"自救"

一个被可达性分析标记为可回收的对象,是有机会进行自救的。前提是:覆写了Object的finalize()方法,且GC还没有执行该对象的finalize()方法。

先来看一下finalize方法的定义

/**

大致翻译一下前两段:当GC判定某一对象不再通过任一形式被引用时,GC会调用该对象的finalize方法。方法执行时,可以进行任何操作,包括将这个对象再次赋值给某一变量引用,但其主要目的还是做一些对象的清除操作。

其实在finalize方法中,只要将这个对象的引用(this)再次赋值给某一变量,这个对象就可以"自救"。

如果一个对象在finalize阶段也没有完成自救,那么就真的要被回收了。

下面演示一个"自救"的例子:

public 

上述代码很简明,可根据注释理解。代码执行结果如下:

6aac8ac7390442577423b278202bc152.png

2 不同引用类型的回收

Java中有四种引用类型,引用强度由强到弱:强引用、软引用、弱引用、虚引用。针对不同的引用类型,GC的回收策略不同。

2.1 强引用

通过关键字new的对象就是强引用对象,强引用指向的对象任何时候都不会被回收,宁愿OOM也不会回收。

2.2 软引用

如果一个对象持有软引用,那么当JVM堆空间不足时,会被回收。

一个类的软引用可以通过java.lang.ref.SoftReference持有。

2.3 弱引用

如果一个对象持有弱引用,那么在GC时,只要发现弱引用对象,就会被回收。

一个类的弱引用可以通过java.lang.ref.WeakReference持有。

2.4 虚引用

几乎和没有一样,随时可以被回收。

通过PhantomReference持有。

3 Stop the World

问题的出现:如果程序一边执行,一边进行可达性分析的标记操作,那么有可能刚标记完一个对象,这个对象又再次被赋值给其他的引用。这样就有可能回收掉正在使用的对象。

解决这个问题的方式就是Stop the World(STW),STW会在所有线程到达一个安全点时,暂停掉所有应用线程的执行,然后开始专心的标记垃圾对象。这样就保证了数据的一致性,不会导致误回收。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349524.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

管理角色认知-新晋管理常常犯的错

背景 管理是一门实践科学,从知道到做到,需要长时间的刻意练习,提前知道那些坑,可以提前规避。 坑1:被动执行 现象: 不主动找活干,等上级派活; 上级有了安排,指望上级替他…

头条号个人中心登录_登陆自己的头条号后台操作步骤

作为一个自媒体新人对自媒体的知识还是不够了解的,有的新人甚至还不知道什么是头条号后台,这篇文章是专为新手写的一篇文章,带你走进你的头条号后台遛一圈。那么什么是头条号后台呢?这里笔者就作下简单的介绍方便新人学习。登陆自…

python保存变量_将python 中的变量保存到本地

如何将python中的变量保存在本地? 将python 的一些代码保存在本地, 特别是一些需要大量运算的结果,例如 机器学习里面的模型,,放在本地,还是比较好用的。下次就可以直接拿出来使用就好。 其实可以 我觉得可…

django filter查询多选_Django:使用filter的pk进行多值查询操作

由于想要做收藏夹的功能,所以希望能够一次性查询出所有id的对象,查看文档,找到了如下方法pk是primary key的缩写,顾名思义pk_in就是primary key在某一个范围内,具体操作(以自带的User为例):User.objects.fi…

csp-c模拟测试「set·read·」

set 题解 只要求一组特解 像入阵曲一样就好了(入阵曲真是好题啊$!$) $(sum[r]-sum[l])\%n0$ 拆成$sum[r]\%nsum[l]\%n$桶里存$sum[l]\%n$每次找$sum[r]$桶里有没有对应的#sum[l]# 存$tong[0]1$,别的先查后存 证明 证明一下正确性 $0$自己合法$(sum[r]\%n)0$不需要找对应 其他都…

JSP,JSF和EL简介

JavaServer页面,JavaServer Faces和表达语言 在本文中,我将研究JavaServer Pages(JSP)和Expression Language(EL),然后将其与JavaServer Faces (JSF)关联。 我将讨论如何…

stream模式不能接受blob文件_一文带你层层解锁文件下载的奥秘

今天带来的主题是关于文件下载,通过本文带你领略文件下载的奥秘。本文会花费你较长的时间阅读,建议先收藏/点赞,然后查看你感兴趣的部分,平时也可以充当当做字典的效果来查询。:) 不整不知道,一整,居然整出…

# 管道已结束_县城这条路启用自来水新管道,看看是否在你家附近...

连日来,县自来水公司的工作人员顶着高温抓紧作业,目前,县城范堤路自来水管道改造工程已过半,预计本月中旬完工。施工现场1目前,盐垣路至掘中路的新管道正在进行对接,为了确保启用新管道后的用水安全&#x…

python 中的eval与exec

eval类似exec,是使用python编译器运行表达式和语句两者区别在于:eval是编译表达式并返回值(如: eval("hello*2") 结果是 hellohello)exec则是运行一部分代码,并且不像eval那样返回结果,exec的返回值永远是None,且exec可运行多行代码(如: exec("l[1,2,3]\nfor i …

启动时指定需要绑定的网卡_为什么小型汽油机在启动时需要拉风门,而汽车却不用?...

很多人都有骑小型摩托车的经验,在启动摩托车时,一般要把“合风”拉上,否则摩托车启动就会很困难。特别是在天气比较寒冷时,如果不拉上合风,摩托车很难启动。但是在汽车上却没有“合风”这个装置,我们在启动…

java 栈和队列实现迷宫代码_Python 实现数据结构中的的栈,队列

栈栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面&#xff…

管理任务执行-如何排任务优先级

背景 工程师出生的管理者擅长做任务管理,凡是明确答应过的事情,一般会如数兑现。 研究的含义 研究模块核心管理规划把事情做对团队建设理顺做事的主体任务管理把事情做出来,产出实实在在的业绩和成果做事【任务管理】是非常重要的管理内容 对…

maven项目 ant_将大型项目从Ant迁移到Maven

maven项目 ant事实是我们处在艰难时期。 我们花了将近三个月的时间将构建机制从Ant迁移到Maven 。 如果您打算在大型项目中进行同样的安排,那是您必须安排的最短时间。 我们仍在努力解决这种迁移带来的一些附带影响,但幸运的是,它们并不是那么…

缩影和掠影_普查员的“酸苦甜” 社区人口普查工作掠影

普查员的“酸苦甜”--社区人口普查工作掠影/十年一度的人口普查即将收官自十月中旬开展摸底工作以来长安路三社区的普查员们伴着晨曦出发,伴着星光回家,走街串巷、爬楼入户。他们中有社区干部、有社区工作者、还有热心的志愿者们,大家都绷着一…

八数码深度优先搜索_深度优先搜索和广度优先搜索

深度优先搜索和广度优先搜索关于搜索&遍历对于搜索来说,我们绝大多数情况下处理的都是叫 “所谓的暴力搜索” ,或者是说比较简单朴素的搜索,也就是说你在搜索的时候没有任何所谓的智能的情况在里面考虑,很多情况下它做的一件事…

element 日期控件 限制开始日期和结束日期

基于element ui中的时间日期控件的开始日期和结束日期的限制用picker-options属性&#xff0c; 当前日期时间器特有的选项。 代码如下&#xff1a; <el-form-itemlabel"开始日期"label-width"90px"prop"startDate"><el-date-pickerv-mo…

JArchitect v2017发布!

我们很高兴地通知您&#xff0c; JArchitect v2017已发布 &#xff0c;现在可以下载 &#xff01; JArchitect是一个分析工具&#xff0c;确实可以让您深入研究代码的结构和质量 。 使用JArchitect&#xff0c;可以使用 代码指标 &#xff0c;使用可视化 图和树图 &#…

[C语言]程序练习(一)

你好&#xff0c;这里是争做图书馆扫地僧的小白。 个人主页&#xff1a;争做图书馆扫地僧的小白_-CSDN博客 目标&#xff1a;希望通过学习技术&#xff0c;期待着改变世界。 目录 前言 一、常量练习 &#xff08;一&#xff09;整型常量 &#xff08;二&#xff09;浮点型常…

如何在程序中不用加号实现加法_程序员那些事 | JavaScript基础(六)

Hello&#xff0c;程序员那些事又与大家见面了&#xff01;JS简易日历先给大家看一下效果&#xff1a;大家可能会觉得&#xff0c;唉~好像跟上节课讲的选项卡差不多&#xff0c;就是十二个按钮&#xff0c;改变this的class&#xff0c;同时下面放十二个div&#xff0c;每次显示…

用友UI层获取机构的方法

U层&#xff1a; UFIDA.U9.UI.PDHelper.PDContext.Current.OrgIDPDContext.Current.OrgRef.CodeColumn 转载于:https://www.cnblogs.com/Xanthus/p/11556836.html