第九节:对象复活

前面“终结操作解密”讲过,需要终结一个对象被认为死亡时,垃圾回收器会强制对象重生,使它的Finalize方法得以调用。Finalize方法调用之后,对象才真正死亡。总之,需要终结的一个对象会经历死亡、重生、再死亡的“三部曲”。一个死亡的对象重生的过程称为复活。

准备调用对象的Finalize方法,这是复活的一种形式。垃圾回收器将一个对象引用放入freachable队列时,对象就从根可达,得以复活。这是必须的,因为只有这样,Finalize方法中的代码才能访问对象的字段。最终,对象的Finalize方法返回,不再有任何根指向对象(因为对象已从freachable队列中移除),对象宣布真正死亡。

但是,如下代码所示,如果Finalize方法在执行时将指向这个对象的指针放到一个静态字段中,又会怎样?

Calss  SomeType

{

~SomeType()

{

Program. s_objHolder=this;

}

}

Static class program

{

Public static object  s_objHolder;

}

在本例中,当SomeType对象的Finalize方法被调用时,对该对象的引用被放入了一个根,使对象从应用程序的代码中可达。对象现在就复活了,垃圾回收期不再认为它是垃圾。应用程序可自由使用该对象。但必须记住的是,该对象曾被终结,所以使用它可能造成无法预测的后果,另外还要注意,如果SomeType的一些字段引用了其他对象,所有的对象都会复活,因为他们都从应用程序 根可达。但请注意,在这些对象中,一部分对象的Finalize方法可能已经调用过。

复活一般不是一件好事,应避免写代码来使用CLR这个功能。只有在应用程序的体系结构要求反复使用同一个对象时,复活才有用处。在这种情况下,当对象使用完毕时,会发生垃圾回收。在对象的Finalize方法中,它将它的this指针赋给另一个根,阻止对象死亡。但是,你想告诉垃圾回收器在下一次使用之后,再次调用Finalize方法,为此,GC类提供了一个ReRegisterForFinalize的静态方法,该方法只有一个参数,也就是对象引用,

Calss  SomeType

{

~SomeType()

{

Program. s_objHolder=this;

GC. ReRegisterForFinalize(this);

}

}

Finalize方法被调用时,它让一个根引用对象,从而时对象复活。然后,Finalize方法调用ReRegisterForFinalize,后者将指定对象的指针添加到终结者列表末尾。当垃圾回收器判断这个对象不可达时(未来在某个时刻,当静态字段为null),他会将对象的指针从终结者列表移到freachable队列,造成对象的Finalize方法被再次调用。记住,复活一个对象,将复活该对象引用的所有对象,可能需要为所有这些对象调用ReRegisterForFinalize,但大多数情况下都不可能是这样做,因为无权访问其他对象的私有字段。

这个例子演示了如何创建一个不断复活,永远死不了的对象,但是一般都不希望对象有这样的行为。更常见的做法实在Finalize方法中条件性的设置一个根来引用对象。

注意 :要保证每一次复活时,都的调用ReRegisterForFinalize方法一次,否则对象的Finalize方法会被调用多次,这是因为每调用一次ReRegisterForFinalize方法,都会在终结列表中追加一条记录项。对象被判断为垃圾后,所有这些记录项都被移到freachable队列中,导致对象的Finalize方法被多次调用。

时间: 2024-10-11 07:28:09

第九节:对象复活的相关文章

JAVA 年轻代收集器 第九节

JAVA 年轻代收集器  第九节 继续上一章所讲的,STW即GC时候的停顿时间,他会暂停我们程序中的所有线程.如果STW所用的时间长而且次数多的话,那么我们整个系统稳定性以及可用性将大大降低. 因此我们在必要的时候需要对虚拟机进行调优,那么调优的主要目标之一就是降低STW的时间,也就是减少Full GC的次数.那么这里我们从调优的角度来分析各个收集器的优势与不足. 首先从作用于年轻代的收集器开始(采用复制的收集算法): Serial收集器:一个单线程收集器,在进行回收的时候,必须暂停其他所有的工

[ExtJS学习笔记]第九节 Extjs5的mvc与mvvm框架结构简介

本文地址:http://blog.csdn.net/sushengmiyan/article/details/38537431 本文作者:sushengmiyan -------------------------------------------------------------资源链接----------------------------------------------------------------------- 翻译来源:http://docs.sencha.com/ext

萌新向Python数据分析及数据挖掘 第一章 Python基础 第九节 类

第一章 Python基础 第九节 类 面向对象编程时,都会遇到一个概念,类,python也有这个概念,下面我们通过代码来深入了解下. 其实类 和函数都是为了节省代码,有了类的的概念,就可以把相同的代码写在父类,子类继承后就可以直接使用,而且通过选择对应的父类就可以直接使用对应父类的内容. 创建和使用类 1 class Dog(): #认识狗这类东西 2 def __init__(self, name, age): #狗是肯定有名字和年龄的,是个狗就有,要用户填写 3 self.name = na

CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第九节

原文链接 第九节:使用CUDA拓展高等级语言 Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在多个国家级的实验室进行大型并行运算的研究,并且是几个新创企业的合伙人.大家可以发邮件到[email protected]与他沟通和交流. 在关于CUDA(Compute Unified Device Architecture,即计算统一设备架构的简称)的系列文章的第八节,我探讨了使用CUDA利用库.在本小节,我

2014年辛星完全解读Javascript第六节 对象

随着面向对象的普及,现在很多语言都在支持面向对象,Javascript也不例外,所谓对象,就是拥有属性和方法的数据.这里的属性其实就是变量,这里的方法,其实就是函数.但是Javascript的面向对象和其他编程语言还是有很大区别的. ************对象************* 1.Javascript中的对象的定义“属性的无序集合,每个属性存放一个初始值.函数或者对象”,也就是说,对象是没有额定顺序的值的数组. 2.Javascript中的对象一般可以分为本地对象.内置对象.宿主对象

Linux学习第九节课-shell脚本编程

Linux第九节课 -------------------------------------------------------------------------------------------------------------------------------- 程序:算法+数据结构 数据:程序的核心 算法:处理数据的方式 程序编程风格 过程式:以指令为中心,数据服务于指令 对象式:以数据为中心,指令服务于数据 高级编程语言 编译:高级语言→编译器→机器代码→执行,例如c,c++等

第九节(对象和引用)

Java把内存划分成两种:一种是栈内存,一种是堆内存 一. 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所 分配的内存空间,该内存空间可以立即被另作他用. 二. 堆内存用来存放由new创建的对象和数组.在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理 1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方.与C++不同

第九节:mybatis关联查询之一对多查询

一对多,是最常见的一种设计.就是 A 表的一条记录,对应 B 表的多条记录,且 A 的主键作为 B 表的外键.这主要看以哪张表为中心,下面的测试数据中,从employee 表来看,一个员工对应一个部门,是一对一关系,如果从部门角度来看,则是一对多的关系,一个部门对应多个员工,本节主要研究一对多的关系. 查询部门的时候将部门对应的所有员工信息也查询出来 1,数据表建立 新建数据表department,有两个字段,插入两条数据如下: id dept_name 1 CIA 2 FSB 新建数据表emp

python学习笔记第九节(迭代器,生成器,三元表达式)

for循环相当于自动调动__iter__ for循环相当于上面这样每次__next__再打印一次 while循环的迭代方式,采用try的方式 判断是否为可迭代 判断是否为迭代器对象 加了蓝色段,可以调用原来的函数名 迭代对象 可以__iter__的迭代器 将__iter__之后的结果的迭代器对象 可以直接__next__的 生成器 迭代到yield后停止,相当于__next__函数加上yield后就是迭代器.可以每次__next__显示,每次显示到yield后停止,相当于return,但是下次_