我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java中回收对象标记和对象二次标记的示例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java中回收对象标记和对象二次标记的示例分析

这篇文章主要介绍Java中回收对象标记和对象二次标记的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

一、对象的标记

什么是标记?怎么标记? 

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

引用计数实现起来比较简单,就是给对象添加一个引用计数器,每当有一个地方引用它时就加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()在什么时候被调用?

有三种情况

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

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

显式的调用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中回收对象标记和对象二次标记的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网行业资讯频道!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java中回收对象标记和对象二次标记的示例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java中回收对象标记和对象二次标记的示例分析

这篇文章主要介绍Java中回收对象标记和对象二次标记的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一、对象的标记1、什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象
2023-05-31

Java中类和对象的示例分析

这篇文章主要介绍了Java中类和对象的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。类可以看成是创建Java对象的模板1、类的定义public class Dog {
2023-06-25

PHP中针对区域语言标记信息的示例分析

这篇文章给大家分享的是有关PHP中针对区域语言标记信息的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。获取及设置当前的区域语言信息首先就是我们可以动态地获取和设置相应的区域语言信息。// # echo $
2023-06-20

java中ThreadLocal对象存储和获取的示例分析

这篇文章主要介绍了java中ThreadLocal对象存储和获取的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Java的特点有哪些Java的特点有哪些1.Java语
2023-06-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录