为了简化编程,System.Runtime.ConstrainedExecution 命名空间定义了一个CriticalFinalizerObject类,其形式如下:
public abstract class CriticalFinalizerObject{
protected CriticalFinalizerObject(){ /* 这里没有代码*/}
// 这是一个Finalize方法
~CriticalFinalizerObject(){/* 这里没有代码*/ }
}
我知道,这个类看起来并无什么特别。但是,CLR以一种非常特殊的方式对待该类及其派生类。具体地说,CLR赋予这个类以下三个很酷的功能。
1,首次构造任何CriticalFinalizerObject派生类型的一个对象时,CLR立即对继承层次结构中的所有Finalize方法进行JIT编译。在构造对象时就编译这些方法,可确保当对象被确定为垃圾以后,本地资源肯定会得到释放。如果不对Finalize方法进行提前编译,那么也许能分配并使用本地资源,但无法保证肯定会释放这些本地资源。内存紧张时,CLR可能找不到足够的内存来编译Finalize方法,这会阻止Finalize方法的执行,造成本地资源泄露。另外,如果Finalize方法中的代码引用了另一个程序集中的一个类型,而且CLR在寻找这个程序集时失败,也会造成资源得不到释放。
2,CLR是在调用了非CriticalFinalizerObject 派生类型的Finalize方法以后,才调用 CriticalFinalizerObject 派生类型的Finalize方法。这样一来,托管资源类就可以在他们的Finalize方法中成功地访问CriticalFinalizerObject 派生类型的对象。例如, FileStream类的Finalize方法可以放心地将数据从内存缓冲区flush到磁盘,它知道此时磁盘文件还没有关闭。
3,如果AppDomain 被一个宿主应用程序(例如Microsoft SQL Server或者Microsoft ASP.NET)强行中断,CLR将调用CriticalFinalizerObject派生类型的Finalize方法。宿主应用程序不再信任它内部运行的托管代码时,也利用这个功能确保本地资源得以释放。