C#.NET GC.Collect垃圾回收机制详解


  C#.NET GC.Collect垃圾回收机制详解
C#.NET GC.Collect垃圾回收机制详解


什么是GC?

GC如其名,就是垃圾收集,当然这里仅就内存而言。Garbage Collector(垃圾收集器,在不至于混淆的情况下也成为GC)以应用程序的root为基础,遍历应用程序在Heap上动态分配的所有对象[2],通过识别它们是否被引用来确定哪些对象是已经死亡的、哪些仍需要被使用。已经不再被应用程序的root或者别的对象所引用的对象就是已经死亡的对象,即所谓的垃圾,需要被回收。这就是GC工作的原理。


GC的必要性


1)、应用程序对资源操作,通常简单分为以下几个步骤:
      为对应的资源分配内存 → 初始化内存 → 使用资源 → 清理资源 → 释放内存

2)、应用程序对资源(内存使用)管理的方式,常见的一般有如下几种:

[1] 手动管理:C,C++,Pascal

[2] 计数管理:COM,Pascal

[3] 自动管理:.NET,Java

3)、但是,手动管理和计数管理的复杂性很容易产生以下典型问题:

[1] 程序员忘记去释放内存

[2] 应用程序访问已经释放的内存

产生的后果很严重,常见的如内存泄露、数据内容乱码,而且大部分时候,程序的行为会变得怪异而不可预测,还有Access Violation等。这个情况在C++、Pascal语言非常常见。

.NET、Java等给出的解决方案,就是通过自动垃圾回收机制GC进行内存管理。这样,问题1自然得到解决,问题2也没有存在的基础。

4)、法自动化的内存管理方式极容易产生bug,影响系统稳定性。


什么是代(Generation)?


代(Generation)引入的原因主要是为了提高性能(Performance),以避免收集整个堆(Heap)。
一个基于代的垃圾回收器做出了如下几点假设:

1、对象越新,生存期越短;

2、对象越老,生存期越长;

3、回收堆的一部分,速度快于回收整个堆。

.NET的垃圾收集器将对象分为三代(Generation0,Generation1,Generation2),不同的代里面的内容如下:

1、G0 小对象(Size<85000Byte):新分配的小于85000字节的对象。

2、G1:在GC中幸存下来的G0对象。

3、G2:大对象(Size>=85000Byte);在GC中幸存下来的G1对象。


C# Code:

object o = new Byte[85000]; //large object
Console.WriteLine(GC.GetGeneration(o)); //output is 2,not 0

//来源:C/S框架网 | www.csframework.com | QQ:23404761



这里必须知道,CLR要求所有的资源都从托管堆(managed heap)分配,CLR会管理两种类型的堆,小对象堆(small object heap,SOH)和大对象堆(large object heap,LOH),其中所有大于85000byte的内存分配都会在LOH上进行。

代收集规则:当一个代N被收集以后,在这个代里的幸存下来的对象会被标记为N+1代的对象。GC对不同代的对象执行不同的检查策略以优化性能。每个GC周期都会检查第0代对象。大约1/10的GC周期检查第0代和第1代对象。大约1/100的GC周期检查所有的对象。

代是指托管内存中不同的区域,对象越老位于的代越靠后,比如:第一次垃圾回收后某个对象未被回收,它可能就会从0代移动到1代,以此类推。
何谓垃圾?


垃圾就是只没有任何对象再和他有引用关系,专业点说就是从这个对象开始找其引用,一直找,如果找到它正在引用一个根,那么这个就是不是垃圾,如果找不到根则这个对象就是垃圾。



什么是根(Root)?


根就是指一个存储位置,包含指向某个引用类型的指针。比如静态变量,全局变量就是根,当前寄存器里面的对象就是根,还有当前调用栈上的参数,局部变量都是根。

另外,垃圾回收开始的时候当前所有线程都将被挂起,开始收集托管堆上的垃圾,收集完了还要压缩内存,然后等待垃圾回收结束以后再恢复这些线程,从这个角度来说,还是少调用垃圾回收,但是不是不能调,要视情况而定。

每个应用程序都包含一组根(root)。每个根都是一个存储位置,其中包含指向引用类型对象的一个指针。该指针要么引用托管堆中的一个对象,要么为null。


在应用程序中,只要某对象变得不可达,也就是没有根(root)引用该对象,这个对象就会成为垃圾回收器的目标。

用一句简洁的英文描述就是:




GC roots are not objects in themselves but are instead references to objects. Any object referenced by a GC root will automatically survive the next garbage collection.




.NET中可以当作GC Root的对象有如下几种:

1、全局变量

2、静态变量

3、栈上的所有局部变量(JIT)

4、栈上传入的参数变量

5、寄存器中的变量

注意,只有引用类型的变量才被认为是根,值类型的变量永远不被认为是根。因为值类型存储在堆栈中,而引用类型存储在托管堆上。


什么时候发生GC
1、当应用程序分配新的对象,GC的代的预算大小已经达到阈值,比如GC的第0代已满;

2、代码主动显式调用System.GC.Collect();

3、其他特殊情况,比如,windows报告内存不足、CLR卸载AppDomain、CLR关闭,甚至某些极端情况下系统参数设置改变也可能导致GC回收。



GC.Collect()的一般用法如下面源码如示:



C# Code:

dpFormulaList.Clear();
dpFormulaList
= null;

inputs.Clear();
inputs
= null;

GC.Collect();

//来源:C/S框架网 | www.csframework.com | QQ:23404761




C# Code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TestDOME
{
  
public partial class Form1 : Form
  {
    
public Form1()
    {
      InitializeComponent();
    }
    
    
private void button1_Click(object sender, EventArgs e)
    {
      
using(Demo de2 = new Demo())
      {
        de2.dt();
      }
      Demo de3
= new Demo();
      de3.Dispose();
      
      Demo1 d1
= new Demo1();
      d1
= null;//设置为空时才可以手动释放
      
GC.Collect();
    }
  }
  
  
public class Demo : IDisposable//继承接口
  
{
  
public void dt()
  {
    
  }
  
~Demo()
  {
    Dispose(
false);
  }
  
  
#region IDisposable Members
  
  
public void Dispose()
  {
    Dispose(
true);
    GC.SuppressFinalize(
true);
  }
  
private bool _disposed = false;//资源释放标志
  
protected virtual void Dispose(bool disposeManageResourse)
  {
    
if (!_disposed)
    {
      
if (disposeManageResourse)
      {
        
//释放托管资源
        
MessageBox.Show("回收资源1");
      }
      _disposed
= true;
    }
  }
  
  
  
#endregion
}

public class Demo1
{
  
~Demo1()
  {
    MessageBox.Show(
"回收资源d1");
  }
}
}

//来源:C/S框架网 | www.csframework.com | QQ:23404761




C/S框架网|原创精神.创造价值.打造精品

扫一扫加微信
C/S框架网作者微信 C/S框架网|原创作品.质量保障.竭诚为您服务

版权声明:本文为开发框架文库发布内容,转载请附上原文出处连接
C/S框架网
上一篇:关于LookupEdit组件选择一条纪录不触发EditValueChanged事件
下一篇:SQL Server 存储过程详解
评论列表

发表评论

评论内容
昵称:
关联文章

C#.NET GC.Collect垃圾回收机制详解
C#.NET CLR垃圾回收机制
C#.NET 消息机制
C#.Net 静态构造器使用详解
C#/.NET 基础学习
C#.Net对象内存模型及堆/栈数据结构详解 (四)
.NET 6 优先队列 PriorityQueue 详解
C#.Net对象内存模型及堆/栈数据结构详解 (一)
C#.Net反射(Reflaction)技术实例详解
C#.Net对象内存模型及堆/栈数据结构详解 (三)
C#.Net对象内存模型及堆/栈数据结构详解 (二)
C#.Net WCF实例详解及源码下载
C#.NET 实体框架EF(Entity Framework)详解
C# WebService代理类详解
C/S开发框架事务处理机制
C#.Net窗体多重继承构造器及Load事件执行顺序详解
C#调用C++编译的DLL详解
C#.NET RESTFul API详解
ASP.NET MVC中几种常用的ActionResult详解
C#.NET C/S结构版本自动升级解决方案2.0详解 (一)

热门标签
.NET5 .NET6 .NET7 APP Auth-软件授权注册系统 Axios B/S B/S开发框架 Bug Bug记录 C#加密解密 C#源码 C/S CHATGPT CMS系统 CodeGenerator CSFramework.DB CSFramework.EF CSFrameworkV1学习版 CSFrameworkV2标准版 CSFrameworkV3高级版 CSFrameworkV4企业版 CSFrameworkV5旗舰版 CSFrameworkV6.0 DAL数据访问层 Database datalock DbFramework Demo教学 Demo下载 DevExpress教程 DOM EF框架 Element-UI EntityFramework ERP ES6 Excel FastReport GIT HR IDatabase IIS JavaScript LINQ MES MiniFramework MIS NavBarControl Node.JS NPM OMS ORM PaaS POS Promise API Redis SAP SEO SQL SQLConnector TMS系统 Token令牌 VS2022 VSCode VUE WCF WebApi WebApi NETCore WebApi框架 WEB开发框架 Windows服务 Winform 开发框架 Winform 开发平台 WinFramework Workflow工作流 Workflow流程引擎 版本区别 报表 踩坑日记 操作手册 代码生成器 迭代开发记录 基础资料窗体 架构设计 角色权限 开发sce 开发技巧 开发教程 开发框架 开发平台 开发指南 客户案例 快速搭站系统 快速开发平台 秘钥 密钥 权限设计 软件报价 软件测试报告 软件简介 软件开发框架 软件开发平台 软件开发文档 软件体系架构 软件下载 软著证书 三层架构 设计模式 生成代码 实用小技巧 收钱音箱 数据锁 数据同步 微信小程序 未解决问题 文档下载 喜鹊ERP 喜鹊软件 系统对接 详细设计说明书 行政区域数据库 需求分析 疑难杂症 蝇量级框架 蝇量框架 用户管理 用户开发手册 用户控件 在线支付 纸箱ERP 智能语音收款机 自定义窗体 自定义组件 自动升级程序