Java回收对象的标记 和 对象的二次标记过程

【八股细文】说说CMS回收过程,为啥初始标记和重新标记需要STW,而并发标记不需要? CMS(Concurrent Mark-Sweep)是一种用于垃圾回收的算法,主要用于减少应用程序停顿时间。:在这个阶段,GC 线程会暂停所有应用线程,然后标记所有的根对象和直接与根对象关联的对象。这个阶段的目的是标记出所有从根对象直接可达的对象,以便后续的并发标记。:在初始标记阶段完成后,GC 线程会与应用程序线程并发执行,标记所有从根对象间接可达的对象。这个阶段的特点是与应用程序线程并发执行,尽量减少停顿时间。 阅读详情

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虚拟机

WinCC与施耐德PLC的Modbus TCP通信实战指南 本文详细解析了西门子WinCC与施耐德PLC通过Modbus TCP协议实现通信的完整实战流程。内容涵盖硬件网络配置、Modbus地址映射核心规则、WinCC驱动连接建立、变量创建及高级数据访问技巧,并提供了常见故障排查思路,帮助工程师高效解决跨品牌设备通信难题。 阅读详情

相关推荐

SGM5860x高精度ADC驱动开发与SPI接口实战指南

本文详细介绍了SGM5860x高精度ADC芯片的驱动开发与SPI接口配置实战。内容涵盖芯片特性、SPI通信设置、寄存器映射、驱动初始化、数据采集处理、校准优化及调试技巧,帮助开发者快速掌握国产24位ADC的应用,提升工业测量项目的精度与稳定性。

vvv99的博客 721

关于GC过程中对象的两次标记

1.前言 前几天面试过程中被问到了垃圾收集,面试官问了我垃圾收集是怎么实现的,然后我就把运行时数据区里的堆里的新生代和老年代介绍了一遍,又指出新生代里的eden和survivor,再说了说复制算法,标记清除和标记整理算法。最后面试官又问我,那你说说怎么判断一个对象可以被回收把,我说了引用为0以及标记对象两次(也就是引用计数器和可达性算法)。重点来了,面试官又问我你说的两次标记,是什么意思呢?我哑口...

hexo-github建立中出现的问题 1631

研一脑电小白日记 之 EEGLAB预处理实战指南

本文为脑电研究新手提供了一份详尽的EEGLAB预处理实战指南。从MATLAB与EEGLAB环境搭建、使用NeuracleEEGFileReader插件导入BDF格式数据开始,逐步讲解了电极定位、滤波、降采样、ICA去伪迹等核心步骤,旨在帮助初学者高效完成脑电数据预处理,为后续分析奠定坚实基础。

weixin_29230649的博客 559

判断对象是否可回收的两次标记过程

第一次标记 如果对象到GC Roots之间没有引用链 则进行第一次标记 第二次标记 如果对象没有调用过finalize方法 或者该方法已经被虚拟机调用过了 则虚拟机视为没有必要执行 将其标记为不可触及对象. 如果对象重写了finalize方法且方法没有被执行过 则将其放入F-Queue对列中 由虚拟机进行执行 如果对象在其finalize方法中建立了连接 则第二次标记是会被移出 即将回收集合 ...

qq_49644209的博客 907

【论文翻译】Enhancing Channel Estimation in High Mobility OTFS Systems: A Novel Pilot-Based Method...

本文介绍了一种用于正交时频空间(OTFS)调制系统的新型基于导频的信道估计方法。我们提出的方法是在ZP-OTFS系统的零填充区域插入一行导频符号,具有减少开销和降低峰均功率比(PAPR)的显著优势。特别是,通过沿多普勒轴分布导频符号,我们的方法在高移动性场景下依然能够提供鲁棒且精确的信道估计,这是像TransPod这种时速超过1000 km/h的运输系统的一个典型特征。这一点至关重要,因为在此类场景下,多普勒频移可能会导致系统性能的严重退化。

Cuby的博客 1212

KITTI数据集下载及解析

KITTI数据集下载及解析 版本 更新时间 更新内容 作者 1 V 1.0 xxx 完成主体内容 W. Xiao 2 文章目录KITTI Dataset1 简介1.1 数据采集平台1.2 坐标系2 数据解析2.1 image文件2.2 velodyne文件2.3 calib文件2.4 label文件3 KITTI可视...

u013086672的博客 5万+

判断对象是否真正能被回收,需要的两个过程

要真正宣告一个对象死亡,至少要经历两次标记过程: 1.对象先进行可达性分析,如果没有发现与GC Roots相连接的引用链,此时该对象将会被第一次标记。 2.接着还要做一次筛选,筛选的条件是此对象是否有必要执行finalize()方法,因为finalize()方法是拯救对象的最后一次机会,所以只有对象没有覆盖finalize()方法或者即使覆盖了也没有拯救自己的意思,或者finalize()方法已经被虚拟机调用过,才能真正宣告一个对象死亡,能够被垃圾回收器回收。 ...

硅脂味咖啡的博客 452

Case-Based Reasoning用于RAG

在做大模型应用RAG的时候,会发现一种特殊的场景,就是基于之前的case进行回答,比如法律咨询、医疗诊断等等。这种情况的问答,需要有强有力的case支持才行,有了case支持,大模型回答会更加准确。CBR这个概念已经很久了,它是一种人工智能推理方法,它的基本思想是:遇到新问题时,先回忆相似的过去案例,再基于这些案例进行调整,得到新问题的解答。Retrieve(检索):在案例库中找到与当前问题最相似的案例。Reuse(复用):借鉴案例的解决方案来应对当前问题。

sinat_28694519的博客 938

java对象的生命周期及回收

在网上看到一篇不错的文章,记录下来备忘。   要理解java对象的生命周期,我们需要要明白两个问题,    1、java是怎么分配内存的 ,2、java是怎么回收内存的。   喜欢java的人,往往因为它的内存自动管理机制,不喜欢java的人,往往也是因为它的内存自动管理。我属于前者,这几年的coding经验让我认识到,要写好java程序,理解java的内存管理机制是多么的重要。任何...

shuaijie506 412

手把手教你用Trae配置Python开发环境(含Claude 3.5代码生成实战)

本文详细介绍了如何使用字节跳动推出的Trae智能开发环境配置Python开发环境,并实战演示了Claude 3.5代码生成功能。从环境准备到项目初始化,再到AI辅助编码和调试优化,全面展示了Trae在提升开发效率方面的强大能力,特别适合Python开发者快速搭建项目和解决复杂问题。

weixin_28309571的博客 977

Windows配置L2TP/IPsec连接

Windows 系统的 L2TP/IPsec 功能,通过配置即可构建加密 VPN 通道。

m0_61806534的博客 1668

JVM学习笔记之四 四种引用和垃圾回收的两次标记

四种引用和两次标记四种引用    java中的数据类型我们知道是分为基本数据类型和引用类型的。基本数据类型是8种,分别是boolean byte short int long double float char,基本数据类型其变量内存中存储的是该变量的值,而引用类型在JDK 1.1中的描述是:如果Reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。此...

tony_java_2017的博客 2559

第11.4节 混合储能系统能量管理

混合储能系统(HESS)的能量管理策略采用分层架构实现多时间尺度优化:调度层(小时级)进行经济优化,协调层(秒级)基于频率分解分配功率,执行层(毫秒级)实现快速跟踪。深度强化学习(DRL)方法通过定义状态空间、动作空间和多目标奖励函数,能有效处理系统不确定性和多目标优化问题。HESS性能评估需综合技术指标(如调节性能Kp值、设备寿命指标)和经济指标(净现值NPV、平准化储能成本LCOS),并遵循"建模-仿真-实验"的闭环流程。

技术工作者 246

java回收象重新利用_浅谈Java回收对象的标记和对象的二次标记过程

浅谈Java回收对象的标记和对象的二次标记过程发布于 2020-6-14|复制链接摘记: 一、对象的标记1、什么是标记?怎么标记?第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理。 至于怎么标记,一般有两种方法:引用计数和可达性分析。引用计数实现起来比较简单,就是给对象添加一个引用计数器 ..一、对象的标记1、什么是标记?怎么标记?第一个问题相信大家都知道,标记就是...

weixin_39559469的博客 176

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

(转)Java回收对象的标记 和 对象的二次标记过程

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

weixin_30768175的博客 305

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【Java系列】浅谈 Java 中对象的创建和销毁过程

在 Java 编程里,对象的创建和销毁是基础且关键的操作,深刻理解这一过程有助于编写出高效、稳定的代码。下面将详细阐述 Java 中对象的创建和销毁过程。

颜淡慕潇 7853

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

GC是如何判断一个对象为"垃圾"的?被GC判断为"垃圾"的对象一定会被回收吗?

java堆内存中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”。那么GC具体通过什么手段来判断一个对象已经”死去”的?

不能说的秘密的博客 2万+

Java中如何标记对象已经死亡

Java中如何标记对象已经死亡    要真正宣告一个对象死亡,至少要经历两次标记过程。 第一次标记 在可达性分析后发现到GC Roots没有任何引用链相连时,被第一次标记; 并且进行一次筛选:此对象是否必要执行finalize()方法; 没有必要执行 没有必要执行的情况: 对象没有覆盖finalize()方法; finalize()方法已经被JVM调用过; 这两种情况就可...

sparrowwf的专栏 513

GC标记回收

1.什么是GCGarbage Collection简称为GC,是垃圾回收的意思、内存处理器是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃。Java语言提供的GC功能可以自动的检测对象是否超过作用域,从而达到自动回收内存的目的,java语言没有提供释放已分配内存的显示操作方法,资源回收工作全部交由GC来完成,程序员不能精确的控制垃圾回收的时机。2.GC的标记GC在

syilt的博客 809

JVM垃圾回收

1.哪些内存需要回收? 1.1.一次标记(可达性分析算法) 有一系列“GCRoots”起点,从这些点开始向下搜索,走过的路径称为“引用链”。若一个对象没有任何引用链可到达GC Roots,那么该对象就是不可用的,即使该对象还与其他对象相关联。 GC Roots类型: ① 虚拟机栈中引用的对象 ② 方法区中类静态属性引用的对象 ③ 方法区中常量引用的对象 ④ 本地方法...

学习猴 329

JVM系列(四) - JVM垃圾回收算法

前言 前面介绍了Java内存运行时区域,其中程序计数器、虚拟机栈、本地方法栈三个区域随线程而生,随线程而灭;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这几个区域的内存分配和回收都具备确定性。在这几个区域内不需要过多考虑回收的问题,因为方法结束或线程结束时,内存自然就跟随着回收了。 Jav...

ahfqb42008的专栏 99

JVM 系列(3) —— 垃圾回收算法

垃圾回收 如何判断对象已死 在 Java 对对象进行回收之前,需要判断哪些对象已死,哪些对象存活,常用的判断方法有两种: 引用计数法和可达性分析法 引用计数法 引用计数法就是在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加一,当引用失效时就减一。当计数器为 0 时,对象便不再被引用。 引用计数法虽然消耗了一些空间,但是原理简单,判定高效,在绝大多数情况下是一个不错的算法。但是引用计数法需要考虑到很多例外的情况,必须要配合大量的额外工作才能正确的工作,比如单纯引用计数法就很难解决对象之间相互循

qq_38219153的博客 176

虚拟机怎么判断对象是否需要回收?

虚拟机怎么判断这个对象是否需要回收? Java虚拟机采用的是可达性分析算法 这个算法的基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索。 搜索所走过的路径称为引用链(Reference Chain), 当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的,即可被回收。 在Java语言中,可作为GC Roots的对象包括: 虚拟机栈(栈帧中的本地变量表)中引用的对象。 方法区中类静态属性引用的对象。 方法区中常量引用的对象。 本地方法栈中Native

lx9876lx的博客 173

GC是如何判断一个对象为"垃圾"的?被GC判断为"垃圾"的对象一定会被回收吗?...

一.GC如何判断一个对象为”垃圾”的 Java堆内存中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”。那么GC具体通过什么手段来判断一个对象已经”死去”的? 1.引用计数算法(已被淘汰的算法) 给对象中添加一个...

191

java中如何判定对象是否可以被回收

一.GC如何判断一个对象为”垃圾”的 java堆内存中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”。那么GC具体通过什么手段来判断一个对象已经”死去”的? 1.引用计数算法(已被淘汰的算法) 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器为0的对象就是不可...

hcgeng的专栏 3379

CMS回收过程,为啥初始标记和重新标记需要STW?

总体来说,CMS 回收过程通过并发标记和并发清除的方式来减少垃圾回收时的停顿时间,但在进行垃圾回收的同时,可能会产生内存碎片问题,需要额外的处理。另外,由于 CMS 是基于标记-清除算法,会产生大量的空闲列表碎片,可能会影响到大对象的分配。初始标记(Initial Mark)和重新标记(Remark)阶段需要 Stop-The-World(STW) 操作,而并发标记(Concurrent Mark)阶段不需要的主要原因是为了减少对应用程序的影响,提高系统的吞吐量和响应性能。

weixin_40501652的博客 900
上一篇: cookie、session机制解释
下一篇: Javac编译与JIT编译
马克吐温
博客等级 码龄10年 11粉丝 43原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值