搜索
首页Javajava教程Java中回收对象的标记以及对象的二次标记过程详解

这篇文章主要介绍了浅谈Java回收对象的标记和对象的二次标记过程的相关内容,小编觉得还是挺不错的,这里给大家分享一下,需要的朋友可以参考。

一、对象的标记

1、什么是标记?怎么标记? 

        第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理。 至于怎么标记,一般有两种方法:引用计数和可达性分析。

引用计数实现起来比较简单,就是给对象添加一个引用计数器,每当有一个地方引用它时就加1,引用失效时就减1,当计数器为0的时候就标记为可回收。这种判断效率很高,但是很多主流的虚拟机并没有采用这种方法,主要是因为它很难解决几个对象之间循环引用的问题,虽然不怎么用了,但还是值得我们学习!


public class Test {
private Object obj;
Public static void main(){
Test t1=new Test();
Test t2=new Test();
t1.obj=t2;
t2.obj=t1;
t1=null;
t2=null;
//如果对象在这行发生gc,那么t1和t2对象是否能被回收
System.gc();
}
}

 可达性分析的基本思路就是:通过将一些称为"GC Roots"的对象作为起始点,从这些节点开始搜索,搜索和该节点发生直接或者间接引用关系的对象,将这些对象以链的形式组合起来,形成一张“关系网”,又叫做引用链。最后垃圾收集器就回收一些不在这张关系网上的对象。如图:

连接GC Roots对象的object是确定还存活的对象,而右边的die obj由于和GCROOTS没有关系,所以会标记为可回收的对象。目前主流的商用虚拟机用的都是类似的方法。那什么对象才能作为“GC Roots”呢?在java中,有四种对象可以作为“GC Roots”

        1:栈帧(第一章的名词)中的引用对象。(栈中的)

        2:静态属性引用的对象。(方法区中的)

        3:常量引用的对象。(方法区中的)

        4:本地方法栈中JNI引用的对象。(本地方法栈中的)

二、对象的二次回收

说过对象的标记,但是不是被标记了就肯定会被回收呢?不知道小伙伴们记不记得Object类有一个finalize()方法,所有类都继承了Object类,因此也默认实现了这个方法。

finalize的工作原理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下一次垃圾收集过程中,才会真正回收对象的内存.所以如果使用finalize(),就可以在垃圾收集期间进行一些重要的清除或清扫工作.
finalize()在什么时候被调用?

有三种情况

1.所有对象被Garbage Collection时自动调用,比如运行System.gc()的时候.

2.程序退出时为每个对象调用一次finalize方法。

3.显式的调用finalize方法

这个方法的用途就是:在该对象被回收之前,该对象的finalize()方法会被调用。这里的回收之前指的就是被标记之后,问题就出在这里,有没有一种情况就是原本一个对象开始不再上一章所讲的“关系网”(引用链)中,但是当开发者重写了finalize()后,并且将该对象重新加入到了“关系网”中,也就是说该对象对我们还有用,不应该被回收,但是已经被标记啦,怎么办呢?

        针对这个问题,虚拟机的做法是进行两次标记,即第一次标记不在“关系网”中的对象。第二次的话就要先判断该对象有没有实现finalize()方法了,如果没有实现就直接判断该对象可回收;如果实现了就会先放在一个队列中,并由虚拟机建立的一个低优先级的线程去执行它,随后就会进行第二次的小规模标记,在这次被标记的对象就会真正的被回收了。

总结:简单说,对象先进行第一次标记,在下一次GC之前会执行对象的finalize()方法。在执行finalize()方法的时候判断对象是否实现了finalize()方法,没有实现直接清除;实现了,将对象放在一个队列中执行finalize方法,进行第二次标记
在java根搜索算法中判断对象的可达性,对于不可达的对象,也并不一定是必须清理。这个时候有一个缓刑期,真正的判断一个对象死亡,至少要经过俩次标记过程:如果对象在进行根搜索后发现没有与GC roots相关联的引用链,那他将会第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法,当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这俩种情况都视为“没有必要执行”。

即当一个对象重写了finalize()方法的时候,这个对象被判定为有必要执行finalize()方法,那么这个对象被放置在F-Queue队列之中,并在稍后由一条由虚拟机自动建立的、低优先级的Finalizer线程去执行。这里所谓的执行是指虚拟机会出发这个方法,但不承诺会等待它运行结束。这样做的原因:如果一个对象在finalize()方法中执行缓慢,或者发生了死循环(极端的情况下),将可能会导致F-Queue队列中的其他对象永久处于等待状态,甚至导致整个内存回收系统崩溃。finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在finalize()中成功拯救自己----只要重新与引用链上的任何建立关联即可,那么在第二次标记时它将会被移出“即将回收”的集合;如果对象这时候没有逃脱,就会被回收。代码示例:参考《深入理解java虚拟机》对应章节

总结

以上是Java中回收对象的标记以及对象的二次标记过程详解的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的?IntelliJ IDEA是如何在不输出日志的情况下识别Spring Boot项目的端口号的?Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本启动Spring...

如何优雅地获取实体类变量名构建数据库查询条件?如何优雅地获取实体类变量名构建数据库查询条件?Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架进行数据库操作时,经常需要根据实体类的属性名构造查询条件。如果每次都手动...

如何利用Redis缓存方案高效实现产品排行榜列表的需求?如何利用Redis缓存方案高效实现产品排行榜列表的需求?Apr 19, 2025 pm 11:36 PM

Redis缓存方案如何实现产品排行榜列表的需求?在开发过程中,我们常常需要处理排行榜的需求,例如展示一个�...

Java对象如何安全地转换为数组?Java对象如何安全地转换为数组?Apr 19, 2025 pm 11:33 PM

Java对象与数组的转换:深入探讨强制类型转换的风险与正确方法很多Java初学者会遇到将一个对象转换成数组的�...

如何将姓名转换为数字以实现排序并保持群组中的一致性?如何将姓名转换为数字以实现排序并保持群组中的一致性?Apr 19, 2025 pm 11:30 PM

将姓名转换为数字以实现排序的解决方案在许多应用场景中,用户可能需要在群组中进行排序,尤其是在一个用...

电商平台SKU和SPU数据库设计:如何兼顾用户自定义属性和无属性商品?电商平台SKU和SPU数据库设计:如何兼顾用户自定义属性和无属性商品?Apr 19, 2025 pm 11:27 PM

电商平台SKU和SPU表设计详解本文将探讨电商平台中SKU和SPU的数据库设计问题,特别是如何处理用户自定义销售属...

在Idea中如何设置SpringBoot项目默认运行配置列表以便团队成员共享?在Idea中如何设置SpringBoot项目默认运行配置列表以便团队成员共享?Apr 19, 2025 pm 11:24 PM

在Idea中如何设置SpringBoot项目默认运行配置列表在使用IntelliJ...

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具