您的位置:首页 > 其它

对象生命周期与可终结对象

2016-03-14 23:23 232 查看
1.值类型和数据类型

值类型分配在栈上面,而引用类型分配在堆上面,在栈上面存在一个空间,该空间保存堆上面的对象的地址。

2.只有一个对象从代码库的任何部分都不可访问时,垃圾回收器才会从堆中删除它,将在下一次垃圾回收时发生。

3..net垃圾回收器是堆的清洁工,他会压缩空的内存块来实现优化(必要时),为辅助这一行为,托管堆保存这一个指针,它精确的指示下一个对象被分配的位置。

4.托管堆分配内存:

一.计算分配对象所需的总内存数(数据成员和基类)

二.检查托管堆,确保有足够空间,如果空间足够,调用类型构造函数,最终将内存中新对象的引用返回给调用者。如果没有足够空间,将进行垃圾回收。

三.在将引用返回给调用者之前,移动下一个对象的指针,指向托管堆上下一个可用的位置。

5.将对象引用设置为null,并不意味着强制垃圾回收器立即启动,并把对象从对上面移除,只是显示的取消引用和之前所指对象之间的连接。

6.引用程序根

根(root)就是一个存储位置,其中保存着对托管堆上一个对象的引用。在一次垃圾回收过程中,运行库将检查托管堆上的对象,判断应用程序是否仍然可以访问他们,即是否还有根。CLR将建立一个对象图,代表堆上可达的每一个对象,垃圾回收器不会在对象图上让一个对象出现两次。在一次垃圾回收过程中,一个对象被标记为终结后,他们就会从内存中清除,堆上的剩余空间被压缩,CLR修改活动的根的集合执行正确内存位置,下一个对象指针被重新调整。

7.对象的代

第0代:从没有被标记为回收的新分配的对象。

第1代:在上一次垃圾回收中没有被回收的对象

第2代:在一次以上的垃圾回收后仍然没有被回收的对象。

8.强制垃圾回收

通过编程使用GC.Collect()强制垃圾回收,如果你确定让垃圾回收器马上检查不可访问对象可能有好处,就可以显示触发一次垃圾回收。

public void Func3()

        { 

            //...

            GC.Collect(0);//并且显示指定回收的代

            GC.WaitForPendingFinalizers();

            //...

        }

9.构建可终结对象

System.Object类定义了名为Finalize()的虚方法。

protected virtual void Finalize(){}

当为自定义的类重写Finalize方法时,就建立了一个地方,来为类型执行必要的清理逻辑。因为这个成员被定义为受保护的,所以不能通过点操作符直接调用该方法。而是在内存中删除这个对象之前,垃圾回收器会调用对象的Finalize()方法。在结构类型上重写Finalize()是不合法的,值类型不分配在堆上,也就不能被回收,但是如果构建的结构包含非托管资源,可以实现IDisposable接口。还有一种情况,当应用程序域从内存中卸载时,CLR自动他的生命周期中创建的每一个可终结对象的终结器。然而大多数类不需要显示的逻辑清理。只有在使用非托管资源时,才可能需要。

在.net凭条中,非托管资源是通过使用PInvoke(平台调用)服务直接调用操作系统的API,或通过一些复杂的COM交互取得。

10.使用终结器语法重写Finalize()方法,这里不能使用预期的override关键字重写Finalize()方法,而是使用终结器语法。

 public class FinalizeClass

    {

        ~FinalizeClass()

        { 

            //清理非托管资源

            //...

        }

    }

当在托管堆上分配对象时,运行库自动确定该对象是否提供了一个自定义的Finalize()方法,如果是这样,对象被标记为可终结的,同时指向这个对象的指针被保存在名为终结队列的内部队列中。终结队列是一个由垃圾回收器维护的表,它指向每一个在从堆上删除之前必须被终结的对象。当垃圾回收器确定从内存中释放一个对象的时间时,它检查终结队列上的每一项,并将对象从堆上复制到另一个可称作终结可达表的托管结构上。此时,下一个垃圾回收将产生另一个线程,为每一个终结可达表中的项调用Finalize()方法。这里进行了两次垃圾回收。

11.通过实现IDisposable接口,构建可处置对象。

public  Interface IDisposable

{

void Dispose();

}

如果实现这个接口,就是假当对象用户不在使用这个对象时,会在这个对象引用离开作用域之前手工调用Dispose();这样对象可以执行任何必要的非托管资源的清除工作,而不会将对象放在终结队列上导致的性能损失。

public class FinalizeClass:IDisposable

    {      

        public void Dispose()

        {

            //清除非托管资源

            //...

        }

    }

调用:

public void Func3()

        { 

            //...

            GC.Collect();

            GC.WaitForPendingFinalizers();

            //...

            FinalizeClass fcls = new FinalizeClass();

            fcls.Dispose();

        }

另一种:

 //当退出using作用域的时候自动调用fcls2.Dispose();

            using (FinalizeClass fcls2 = new FinalizeClass())

            { 

                //

            }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: