第六节:终结操作解密

终结操作表面上视乎很简单:创建一个对象,当它被回收时,它的Finalize方法会得到调用。但是一旦深研究下去,就会发现终结操作原非这么简单。

应用程序创建一个新对象时,new操作符会从堆中分配内存。如果对象的类型定义了Finalize方法,那么在该类型的实例构造函数调用之前,会将指向该对象的一个指针放到终结列表(finalization list)中。终结列表是由垃圾回收器控制的一个内部数据结构。列表中的每一项都指向一个对象- 在回收该对象的内存之前,应调用他的Finalize方法。

下图包含了几个对象的堆。有的对象从应用程序的根可达,有的不可达。对象C、E、F、I、j被创建时,系统检测到这些对象的类型定义了Finalize方法,所以指向这些对象的指针添加到终结者列表中

虽然System.Object定义了一个Finalize方法,但是CLR知道忽略它。也就是说,构造一个类的实例时,如果该类型的Finalize方法时从System.Object继续的,就不认为这个对象时可终结的。类型必须重写Object的Finalize方法,这个类以及派生类型的对象才被认为是可终结的。

垃圾回收开始时,对象B,E,G,H,I和J被判定为垃圾。垃圾回收器扫描终结列表以查找指向这些对象的指针。找到指针后,该指针回从终结列别中移除,并追加到freachable队列中,freachable是垃圾回收期的另一个内部数据结构。Freachable队列中的每个指针都代表其Finalize方法已准备好调用一个对象,下图是展示回收完毕之后的托管堆。

B,G,H占用的内存已经被回收,因为他们没有Finalize方法。但是,对象E,I和J占用的内存暂时不能回收,因为他们的Finalize方法还没有调用。

一个特殊的高优先级CLR线程专门负责调用Finalize方法。使用专用的线程可以避免潜在的线程同步问题。Freachable为空时(这是常见的情况),该线程将睡眠。但一旦队列中有对象出现,该线程就会被唤醒,将每一项从freachable队列中移除,并调用每个对象的Finalize方法。由于该线程的特殊工作方式,Finalize中的代码不应该对执行代码的线程做出任何假设。例如,不应该在Finalize方法中访问线程的本地存储。

CLR未来可能使用多个终结者线程。所以,你写的代码不应假设Finalize方法被连续调用。换言之,如果Finalize方法中的代码要接触到共享的状态,就应该使用线程同步锁。在只有一个终结器线程的情况下,可能有多个CPU分配可终结的对象,但是只有一个线程执行Finalize方法,这回造成线程可能跟不上分配的速度,造成性能和伸缩性方面的问题。

终结列表和Finalize之间的交互非常有意思。首先,让我告诉你freachable队列的这个名称的由来。F明显代表终结(Finalization);freachable队列中的每一个记录项都是对托管堆中的一个对象的引用,该对象的Finalize方法被调用。Reachable意味着可达的。换言之,可将freachable队列看成像静态字段那样的一个根。因此,如果一个对象在freachable中,它就是可达的,不是垃圾。

简单的说,当一个对象不可达时,垃圾回收器就把它视为垃圾。但是,当垃圾回收器将对象的引用从终结者列表移到freachable列表中时,对象不再被认为是垃圾,其内存不能被回收。标记freachable对象时,这些对象的引用类型的字段所引用的对象也会被递归标记,所有这些对象都会在垃圾回收过程中存活下来,到这个时候垃圾回收器才结束对垃圾的标记。由于一些原本被认为是垃圾的对象被重认为不是垃圾,所以从某种意义上将,这些对象复活了,然后,垃圾器开始压缩可回收的内存,特殊的CLR线程清空freachable队列,并执行每个对象的Finalize方法。

垃圾回收期下一次调用时,会发现已终结的对象成为真正的垃圾,因为应用程序的根不再指向它,freachable队列也不再指向它。所以这些对象的内存会直接被回收。整个过程中可终结的对象需要执行两次垃圾回收才能释放他们的内存,在实际应用程序中,对象可能被提升到另一代,所以可能要求不止进行两次垃圾回收。

时间: 2024-12-29 02:04:13

第六节:终结操作解密的相关文章

第一百二十六节,JavaScript,XPath操作xml节点

第一百二十六节,JavaScript,XPath操作xml节点 学习要点: 1.IE中的XPath 2.W3C中的XPath 3.XPath跨浏览器兼容 XPath是一种节点查找手段,对比之前使用标准DOM去查找XML中的节点方式,大大降低了查找难度,方便开发者使用.但是,DOM3级以前的标准并没有就XPath做出规范:直到DOM3在首次推荐到标准规范行列.大部分浏览器实现了这个标准,IE则以自己的方式实现了XPath. 一.IE中的XPath 在IE8及之前的浏览器,XPath是采用内置基于A

第三百七十六节,Django+Xadmin打造上线标准的在线教育平台—创建用户操作app,在models.py文件生成5张表,用户咨询表、课程评论表、用户收藏表、用户消息表、用户学习表

第三百七十六节,Django+Xadmin打造上线标准的在线教育平台-创建用户操作app,在models.py文件生成5张表,用户咨询表.课程评论表.用户收藏表.用户消息表.用户学习表 创建名称为app_operation的用户操作APP,写数据库操作文件models.py models.py文件 #!/usr/bin/env python # -*- coding:utf-8 -*- from __future__ import unicode_literals from datetime i

第六节课:元组和集合

第六节课:元组合集合 首先,看一下英文对应词汇“迭代”->"iteration"->(computer science) a single execution of a set of instructions that are to be repeated; "the solution took hundreds of iterations" “递归”->“recurse"->To execute a procedure recur

NHibernate.3.0.Cookbook第一章第六节Handling versioning and concurrency的翻译

NHibernate.3.0.Cookbook第一章第六节Handling versioning and concurrency的翻译 第一章第二节Mapping a class with XML第一章第三节Creating class hierarchy mappings第一章第四节Mapping a one-to-many relationship第一章第五节Setting up a base entity class Handling versioning and concurrency

centos mysql 实战 第六节课 字符集

centos mysql 实战 第六节课    字符集 一定要研究清楚mysql安装脚本 字符集 乱码数据迁移1. 理解字符集怎么会事2. 不同的字符集进行转换 什么是字符集gbk , utf8 gb2312 latin1 一套符号编码规则 字符串都必须有相应的字符集,除了二进制没有字符集 校验字符集的概念流式传输 多字节latin1 单字节gbk 2字节utf8 3字节校验字符集的概念, 字为单位归类的方法,就是3类xxx_bin 以二进制形式存储区分大小写 SHOW CHARACTER SE

基于Extjs的web表单设计器 第六节——界面框架设计

基于Extjs的web表单设计器 基于Extjs的web表单设计器 第一节 基于Extjs的web表单设计器 第二节——表单控件设计 基于Extjs的web表单设计器 第三节——控件拖放 基于Extjs的web表单设计器 第四节——控件拖放 基于Extjs的web表单设计器 第五节——数据库设计 基于Extjs的web表单设计器 第六节——界面框架设计 基于Extjs的web表单设计器 第七节——取数公式设计 基于Extjs的web表单设计器 第八节——表单引擎设计 这一节我给大家介绍一下表单设

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

原文链接 第六节:全局内存和CUDA RPOFILER  Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在多个国家级的实验室进行大型并行运算的研究,并且是几个新创企业的合伙人.大家可以发邮件到[email protected]与他沟通和交流. 在关于CUDA(Compute Unified DeviceArchitecture,即计算统一设备架构的简称)的系列文章的第二节,我探讨了内存性能和在rever

Powershell管理系列(二十六)PowerShell操作之批量导出&导入邮箱

-----提供AD\Exchange\Lync\Sharepoint\CRM\SC\O365等微软产品实施及外包,QQ:185426445.电话18666943750 项目中有时候做跨林邮箱迁移的时候,条件不成熟,比如安全考虑或者其他考虑,不能做双林信任,这样就提出了一个问题,历史邮件需要使用的话怎么办,一个简单高效的解决办法就是从源森林批量导出邮件为.pst文件,在批量导入到目的域森林,具体操作如下: 1.赋予管理账号邮件导入导出权限,命令如下: cls whoami New-Manageme

第三百一十六节,Django框架,中间件

第三百一十六节,Django框架,中间件 django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法. 在django项目的settings模块中,有一个 MIDDLEWARE变量,其中每一个元素就是一个中间件(也就是一个中间件模块的一个类),如下. settings模块中 #中间件 MIDDLEWARE = [ 'django.middleware.security.Securit