.net中GC原理浅析

简介:

GC(Garbage Collection)垃圾收集,指的是在.net中垃圾内存收集的机制。

首先要了解的几点:

  1. 在.net中,托管代码的内存管理是自动的,由GC进行管理。但是对于非托管代码,.net就无法自动管理了。
  2. CLR运行时候,内存分为“托管堆”和“栈”两个部分。其中,栈是用于存储值类型的数据,托管堆是用于存储引用类型的变量。其中托管堆是GC处理的内存部分。
  3. 进程中每个线程都有自己的堆栈。

 

对于托管代码的GC原理解读:

垃圾判定:

回收垃圾首先要知道什么是垃圾,一个变量如果在其生存期内的某一时刻已经不再被引用,那么,这个对象就有可能成为垃圾。

public static void Main()
              {
                 string sGarbage = "I'm here";
           //下面的代码没有再引用s,它已经成为垃圾对象---当然,这样的代码本身也是垃圾;
            //此时如果执行垃圾收集,则sGarbage可能已经魂归西天
                  Console.WriteLine("Main() is end");
              }

 

 

对象代龄:

GC认为,越晚创建的对象越短命,所以,其引入一个“代龄”的概念来划分对象生存级别

这个代龄划分机制简要来说是一代新人换旧人:

 内存代龄

CLR初始化后的第一批被创建的对象被列为0代对象。CLR会为0代对象设定一个容量限制,当创建的对象大小超过这个设定的容量上限时,GC就会开始工作,工作的范围是0代对象所处的内存区域,然后开始搜寻垃圾对象,并释放内存。当GC工作结束后,幸存的对象将被列为第1代对象而保留在第1代对象的区域内。此后新创建的对象将被列为新的一批0代对象,直到0代的内存区域再次被填满,然后会针对0代对象区域进行新一轮的垃圾收集,之后这些0代对象又会列为第1代对象,并入第1代区域内。第1代区域起初也会被设上一个容量限制值,等到第1代对象大小超过了这个限制之后,GC就会扩大战场,对第1代区域也做一次垃圾收集,之后,又一次幸存下来的对象将会提升一个代龄,成为第2代对象。


    可见,有一些对象虽然符合垃圾的所有条件,但它们如果是第1代(甚至是第2代老臣)对象,并且第1代的分配量还小于被设定的限制值时,这些垃圾对象就不会被GC发现,并且可以继续存活下去。

 

 

对于非托管代码,GC不能自动收集垃圾,需要的方法有两种:1,重写让GC自动调用的Finalize方法。 2,实现IDispose提供给我们显示调用的方法Dispose()

  1. Finalize

~ClassName() {//释放你的非托管资源}

Finalize是由GC负责调用,是一种自动释放的方式。

问:为什么说实现了Finalize方法的对象必需等两次GC才能被完全释放?

 有Finalize函数的两次GC回收

Msdn中的解释:实现 Finalize 方法或析构函数对性能可能会有负面影响,因此应避免不必要地使用它们。用 Finalize 方法回收对象使用的内存需要至少两次垃圾回收。当垃圾回收器执行回收时,它只回收没有终结器的不可访问对象的内存。这时,它不能回收具有终结器的不可访问对象。它改为将这些对象的项从终止队列中移除并将它们放置在标为准备终止的对象列表中。该列表中的项指向托管堆中准备被调用其终止代码的对象。垃圾回收器为此列表中的对象调用 Finalize 方法,然后,将这些项从列表中移除。后来的垃圾回收将确定终止的对象确实是垃圾,因为标为准备终止对象的列表中的项不再指向它们。在后来的垃圾回收中,实际上回收了对象的内存。

        

         第一次的GC做的事情是:1将有终结器的对象放到准备终结列表中,并执行Finalize方法。2 实际删除对象内存。

  1. Dispose

Dispose是提供给我们显示调用的方法。由于对Dispose的实现很容易出现问题,所以在一些书籍上(如《Effective C#》和《Applied Microsoft.Net Framework Programming》)给出了一个特定的实现模式:

class DisposePattern :IDisposable
    {
        private System.IO.FileStream fs = new System.IO.FileStream("test.txt", System.IO.FileMode.Create);

        ~DisposePattern()
        {
            Dispose(false);
        }       

        IDisposable Members#region IDisposable Members

        public void Dispose()
        {
            //告诉GC不需要再调用Finalize方法,
            //因为资源已经被显示清理
            GC.SupdivssFinalize(this);

            Dispose(true);
        }

        #endregion
                
        protected virtual void Dispose(bool disposing)
        {
            //由于Dispose方法可能被多线程调用,
            //所以加锁以确保线程安全
            lock (this)
            {
                if (disposing)
                {
                    //说明对象的Finalize方法并没有被执行,
                    //在这里可以安全的引用其他实现了Finalize方法的对象
                }

                if (fs != null)
                {
                    fs.Dispose();
                    fs = null; //标识资源已经清理,避免多次释放
                }
            }
        }
    }

注: 关键字using()中包含的变量就需要实现了IDispose借口,当出了using的范围的时候会自动使用Dispose方法。

 



本文转自轩脉刃博客园博客,原文链接:http://www.cnblogs.com/yjf512/archive/2010/09/14/1825518.html,如需转载请自行联系原作者

相关文章
|
2月前
|
机器学习/深度学习 算法 网络架构
【CVPR2017】AOD-Net:端到端的除雾网络(原理&实操)
【CVPR2017】AOD-Net:端到端的除雾网络(原理&实操)
368 0
【CVPR2017】AOD-Net:端到端的除雾网络(原理&实操)
|
编解码 分布式计算 Java
基于 netty 封装的超简单通俗易用 服务端客户端交互框架 《net-framework》原理,源码和使用说明,开箱即用,只需要开发业务逻辑,完全自定义无限扩充 [结尾附github源码]
基于 netty 封装的超简单通俗易用 服务端客户端交互框架 《net-framework》原理,源码和使用说明,开箱即用,只需要开发业务逻辑,完全自定义无限扩充 [结尾附github源码]
基于 netty 封装的超简单通俗易用 服务端客户端交互框架 《net-framework》原理,源码和使用说明,开箱即用,只需要开发业务逻辑,完全自定义无限扩充 [结尾附github源码]
|
存储 开发框架 Java
【CLR C#】浅谈.Net的GC(垃圾回收)机制及其整体流程
在.NET程序开发中,为了将开发人员从繁琐的内存管理中解脱出来,将更多的精力花费在业务逻辑上,CLR提供了自动执行垃圾回收的机制来进行内存管理,开发人员甚至感觉不到这一过程的存在。.NET程序可以找出某个时间点上哪些已分配的内存空间没有被程序使用,并自动释放它们。自动找出并释放不再使用的内存空间机制,就称为垃圾回收机制。本文主要介绍.Net中的GC(垃圾回收)机制及其整体流程。
【CLR C#】浅谈.Net的GC(垃圾回收)机制及其整体流程
|
存储 开发框架 安全
浅入.NETCore中的内存和GC知识
浅入.NETCore中的内存和GC知识
529 0
浅入.NETCore中的内存和GC知识
|
存储 开发框架 .NET
ASP.NET Core 中jwt授权认证的流程原理
ASP.NET Core 中jwt授权认证的流程原理
227 0
ASP.NET Core 中jwt授权认证的流程原理
|
SQL 开发框架 前端开发
Asp.net core项目实战 新闻网站+后台 源码、设计原理、视频教程
Asp.net core项目实战 新闻网站+后台 源码、设计原理、视频教程
304 0
Asp.net core项目实战 新闻网站+后台 源码、设计原理、视频教程
|
开发框架 负载均衡 网络协议
.NET WebSocket 核心原理初体验
本文将利用WebSockets(SignalR的一部分)搭建一个可双向通信的ASP.NETCore5应用。
.NET WebSocket 核心原理初体验
|
开发框架 前端开发 中间件
ASP.NET Core端点路由 作用原理
端点路由(Endpoint Routing)最早出现在ASP.NET Core2.2,在ASP.NET Core3.0提升为一等公民。
ASP.NET Core端点路由 作用原理
|
XML 开发框架 负载均衡
抽丝剥茧:浅议ASP.NET Cookie的生成原理
  前言   可能有人知道 Cookie的生成由 machineKey有关, machineKey用于决定 Cookie生成的算法和密钥,并如果使用多台服务器做负载均衡时,必须指定一致的 machineKey用于解密,那么这个过程到底是怎样的呢?   如果需要在 .NETCore中使用 ASP.NETCookie,本文将提到的内容也将是一些必经之路。   抽丝剥茧,一步一步分析   首先用户通过 AccountController->Login进行登录:   //   // POST: /Account/Login   public async Task Login(LoginV
194 0
|
.NET 开发框架
asp.net原理笔记----页面控件类型,页面状况和asp.net编译过程
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq1010885678/article/details/37543103 通过查看asp.
957 0