热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

二次标记过程,java面相对象开发和面相过程开发

Java回收对象的标记和对象的二次标记过程一、对象的标记1、什么是标记?怎么标记?第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收

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


推荐阅读
  • 本文详细介绍了 Apache Jena 库中的 Txn.executeWrite 方法,通过多个实际代码示例展示了其在不同场景下的应用,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
  • 深入理解Java泛型:JDK 5的新特性
    本文详细介绍了Java泛型的概念及其在JDK 5中的应用,通过具体代码示例解释了泛型的引入、作用和优势。同时,探讨了泛型类、泛型方法和泛型接口的实现,并深入讲解了通配符的使用。 ... [详细]
  • 本文提供了使用Java实现Bellman-Ford算法解决POJ 3259问题的代码示例,详细解释了如何通过该算法检测负权环来判断时间旅行的可能性。 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ... [详细]
  • 本文详细介绍了Java中的访问器(getter)和修改器(setter),探讨了它们在保护数据完整性、增强代码可维护性方面的重要作用。通过具体示例,展示了如何正确使用这些方法来控制类属性的访问和更新。 ... [详细]
  • andr ... [详细]
  • Scala 实现 UTF-8 编码属性文件读取与克隆
    本文介绍如何使用 Scala 以 UTF-8 编码方式读取属性文件,并实现属性文件的克隆功能。通过这种方式,可以确保配置文件在多线程环境下的一致性和高效性。 ... [详细]
  • 本文详细介绍了中央电视台电影频道的节目预告,并通过专业工具分析了其加载方式,确保用户能够获取最准确的电视节目信息。 ... [详细]
  • 本文详细探讨了JDBC(Java数据库连接)的内部机制,重点分析其作为服务提供者接口(SPI)框架的应用。通过类图和代码示例,展示了JDBC如何注册驱动程序、建立数据库连接以及执行SQL查询的过程。 ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 深入了解 Windows 窗体中的 SplitContainer 控件
    SplitContainer 控件是 Windows 窗体中的一种复合控件,由两个可调整大小的面板和一个可移动的拆分条组成。本文将详细介绍其功能、属性以及如何通过编程方式创建复杂的用户界面。 ... [详细]
author-avatar
唯美爱人2014
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有