惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
S
Secure Thoughts
Google DeepMind News
Google DeepMind News
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Security Affairs
TaoSecurity Blog
TaoSecurity Blog
Cloudbric
Cloudbric
Cisco Talos Blog
Cisco Talos Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
H
Heimdal Security Blog
The Last Watchdog
The Last Watchdog
T
Threatpost
Hacker News: Ask HN
Hacker News: Ask HN
Security Latest
Security Latest
Know Your Adversary
Know Your Adversary
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Securelist
Microsoft Azure Blog
Microsoft Azure Blog
The GitHub Blog
The GitHub Blog
阮一峰的网络日志
阮一峰的网络日志
D
Docker
V
Vulnerabilities – Threatpost
Attack and Defense Labs
Attack and Defense Labs
Hugging Face - Blog
Hugging Face - Blog
W
WeLiveSecurity
Engineering at Meta
Engineering at Meta
aimingoo的专栏
aimingoo的专栏
Last Week in AI
Last Week in AI
L
LINUX DO - 热门话题
NISL@THU
NISL@THU
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Cloudflare Blog
博客园_首页
P
Privacy International News Feed
Scott Helme
Scott Helme
N
News and Events Feed by Topic
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
T
Tenable Blog
H
Hacker News: Front Page
N
News and Events Feed by Topic
罗磊的独立博客
Google Online Security Blog
Google Online Security Blog
S
Security @ Cisco Blogs
Hacker News - Newest:
Hacker News - Newest: "LLM"
A
About on SuperTechFans
有赞技术团队
有赞技术团队
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
G
GRAHAM CLULEY
Application and Cybersecurity Blog
Application and Cybersecurity Blog

博客园 - 徐鸿翼

《Programming .Net Components》学习笔记(十七) 离开家乡,前往北京 LINQ to SQL可视化调试工具 LINQ to SQL更新数据库操作 《Programming .Net Components》学习笔记(十六) 《Programming .Net Components》学习笔记(十五) 《Programming .Net Components》学习笔记(十四) LINQ的数据库查询应用 《Programming .Net Components》学习笔记(十三) 代码的坏味道,重构,模式 《Programming .Net Components》学习笔记(十二) 《辐射3》的宣传动画 《Programming .Net Components》学习笔记(十一) Visual Studio “Orcas”中LINQ设计器的使用 《Programming .Net Components》学习笔记(十) 乔布斯与盖茨历史性对话实录 LINQ的数据库支持 《Programming .Net Components》学习笔记(九) 记住今天,《Starcraft II》在暴雪精英赛上公布
《Programming .Net Components》学习笔记(八)
徐鸿翼 · 2007-05-17 · via 博客园 - 徐鸿翼

.NET对象不会知道它们何时会成为垃圾,当托管堆被压缩时成为垃圾的对象会直接被覆写。这样就带来一个问题:如果对象持有比较大的消耗的资源(如文件,连接,通讯端口,数据结构,同步处理等等),那么对象应如何处理和释放这些资源那?为了解决这些问题,.Net提供了“object finalization(对象终结)”。如何对象有特殊的清理要做,那么它可以实现Finalize()的方法定义:

    public static class GC

    {

        public static void Collect();

        /* Other methods and members */

    }

当垃圾收集器判定一个对象为垃圾时,它会检查对象的元数据。如果对象实现了Finalize()方法,垃圾收集器就不会销毁这个对象。而是把它标记为“可达对象”(所以对象不会通过压缩托管堆的方式被覆写),然后移动对象从它的原始图表中到一个称为“finalization queue(终结队列)”的特殊队列中。这个队列实质上仅仅是另一个对象图表,队列的根保持着对象的可达性。垃圾收集器接下来继续执行收集垃圾和压缩托管堆。期间,一个分离的线程将迭代终结队列中的所有对象,调用每个对象上的Finalize()方法,让每个对象进行清理工作。Finalize()方法执行完毕后,垃圾收集器会从队列中移除对象。

一、显式垃圾收集

可以使用定义在System命名空间中的GC类中的Collect()方法显式触发垃圾收集:

    public static class GC

    {

        public static void Collect();

        /* Other methods and members */

    }

但是,最好不要以任何方式显式进行垃圾收集。垃圾收集是一个高消耗的操作,包括对象图表扫描,线程上下文转换(thread context switches),线程的挂起和恢复,潜在地磁盘访问,以及广泛的使用反射机制来读取对象元数据。启动垃圾收集机制的原因经常是因为想要调用Finalize()方法来清理对象持有的资源。可以使用确定性终结来代替来垃圾收集机制实现清理功能(后面会讲到)。

也可以使用HandleCollector辅助类来触发垃圾回收机制,.NET 2.0中的System.Runtime.InteropServices命名空间中:

    public sealed class HandleCollector

    {

        public HandleCollector(string name, int initialThreshold, int maximumThreshold);

        public HandleCollector(string name, int initialThreshold);

        public void Add();

        public void Remove();

        public int InitialThreshold { get;}

        public int MaximumThreshold { get;}

        public string Name{get:}

    }

HandleCollector允许保存高消耗的非托管资源的内存地址,如Windows或文件处理。为托管的每种资源类型使用一个HandleCollector对象。HandleCollector用来处理这样的对象——在内存总量中消耗较少的,但持有着高消耗的非托管处理.无论何时通过HandleCollector分配一个新的非托管资源监视,可以调用Add()方法。当要在Finalize()方法中取消资源分配,可以调用Remove()方法。在内部,HandleCollector维护着一个计数器,它的增减基于Add()和Remove()的调用。可见实际上HandleCollector的功能就是每一种处理类型的单纯的引用计数器。当构造一个新的HandleCollector对象时,指定initialmaximum thresholds。无论多少资源分配,只要在初始限定之内,就不会有任何垃圾回收实现。如果请求Add()方法并且资源计数超过了初始限定(但仍在最大限定之内),垃圾回收机制或许会发生,还基于一个自校正试探(a self-tuning heuristic)。如果请求Add()并且资源计数超过最大限定,那么垃圾回收机制总是会启动。

但是,使用HandleCollector会带来几个棘手的问题:

1.   怎样来定义限定的值?这些值可能在用户环境和同一用户超时之间发生变化。

2.   组件如何得知在同一计算机哪些其他应用程序是做相同处理的?

3.   如果触发了垃圾回收机制并且HandleCollector对象维护的处理不是垃圾,那么将会结束垃圾回收的支出但从中得不到任何好处。

综上所述,使用HandleCollector是一个不成熟的优化技术,应避免使用它。

二、Finalize()方法实现

在实现Finalize()方法时,需注意以下几点:

1.        当实现Finalize()时,注意同时也请求基类的Finalize()方法,来让基类执行它的清理:

        protected override void Finalize()

        {

            /* Object cleanup here */

            base.Finalize();

        }

典型的.NET类型System.Object包含了一个没有任何实现的受保护Finalize()方法,但无论基类是否确切的提供了Finalize()方法,都要请求它。

2.        确保定义Finalize()为一个protected方法,避免把Finalize()定义为private方法,因为这样可以预防从子类中调用Finalize()而发生错误。有趣的是,.NET通过反射机制来调用Finalize()方法,而不受访问限制的影响。。。

3.        避免中止请求,因为这将阻碍在队列中所有其他对象的终极操作,直到中止请求返回。

4.        终结必须不依赖于“线程亲和”来执行清理。线程亲和是组件设计的假设,假设组件实例总是运行于同一线程中。但是,Finalize()会在单独的垃圾回收线程中被请求,而不会在任何用户线程中。因而将不能访问任何在该特殊线程中的资源,如线程本地存储或线程相关静态变量。

5.        终结必须不依赖于特定的顺序(如对象A的资源释放必须在对象B之后)。两个对象应该可以以任意顺序添加到队列中去。

6.        即使在面对异常时请求基类的Finalize()实现也是非常必要的,可以通过try/finally机制来处理:

        protected override void Finalize()

        {

            try

            {

                /* Object cleanup here */

            }

            finally

            {

                base.Finalize();

            }

        }

基于上面几点足够适用于每一个类,C#编译器已经内建支持生成模板Finalize()代码。在C#中可以不提供Finalize()方法,而是提供一个C#析构器。编译器会把析构器转换定义为Finalize()方法,其中包含了异常处理机制和对基类Finalize()方法的请求:

    public class MyClass

    {

        public MyClass() { }

        ~MyClass()

        {

            //destructor code

        }

    }

下面是编译器实际生成的代码:

    public class MyClass

    {

        public MyClass() { }

        protected override void Finalize()

        {

            try

            {

                //destructor code

            }

            finally

            {

                base.Finalize();

            }

        }

    }

如果试图同时定义析构器和Finalize()方法,则编译器会产生一个编译错误。或者显式请求基类的Finalize()方法也会得到一个错误。如在类层次中的每个类都具有析构器,编译器生成的代码会按顺序请求每一个析构器,从最底层子类到最高层基类。

根据原版英文翻译总结的,所以不足和错误之处请大家不吝指正,谢谢:)