.Net的GC垃圾回收原理及实现

 更新时间:2021年9月22日 09:59  点击:1269

一、先了解下必备的知识前提

内存中的托管与非托管,可简单理解为:

托管:可借助GC从内存中释放的数据对象(以下要描述的内容点)

非托管:必须手工借助Dispose释放资源(实现自IDisposable)的对象

内存中有栈和堆的概念区分,仅简单说明:

栈:先进后出 的特点(这里不再详细阐述)

堆:存放数据对象实例的内存空间(以下要描述的内容点)

二、.Net GC的简单描述

GC垃圾回收是对于内存堆的处理过程。

当一个应用程序进程创建时,会为此应用程序在物理内存堆中分配一块虚拟的连续性内存空间,以供应用程序后续运行时存放产生的数据对象实例。

GC是一个独立的进程,用来自动维护管理内存堆中的空间分配和释放。它通过一个或多个线程进行垃圾回收,默认启用后台线程垃圾回收。(关于前台线程与后台线程,可参考其它)

三、.Net平台的GC垃圾回收,什么时候会被触发呢?

1、当被分配的堆中虚拟内存空间不够用时,系统会自动 回收/压缩/扩大 被分配的虚拟内存块,以适应新产生的数据对象存储。

2、当整个物理内存不够用时,系统会自动 回收/压缩 各个进程占用的内存空间,以适应新产生的数据对象存储。

3、当应用程序中手动触发GC回收时,GC按照手动指定的方式进行垃圾回收。

四、从作用域上 去理解堆中的代

先这样去理解吧

假设一个实例变量声明时的作用域较大,那它就不会马上被回收,因为作用域大的因素,有可能后续程序时常还会被用到。

假设一个实例变量声明时的作用域较小,那它就有可能被优先回收,因为生存周期较短,过了作用域范围,此变量不会再被使用。

假设一个静态的或全局的作用域变量,那它通常不会被回收,因为这样的全局声明会在任意代码段长期被使用。

所以,为了更好的回收,堆中将各数据对象实例归纳为:0代、1代、2代

0代:临时或最新创建的数据对象实例。最常被回收的对象实例。

1代:一段时间内再次使用的数据对象实例,生命周期较长的数据对象实例。较少被回收的对象实例。

2代:常住内存的对象实例,如:静态类型,全局作用域等的对象实例。通常为应用程序退出后回收。

五、堆中对象 在代之间的转移:幸存者的提升

应用程序持续运行中,

新创建的对象首先被放在0代中,当运行一段时间后,有些变量超出了自己所在的作用域,不会再被使用,会被GC清理;

由于有些变量作用域大,当前还未超出自己所在的作用域,接下来可能还会被使用,所以GC不会清理;

0代中,有些数据对象实例会被GC清理,有些数据实例对象未被GC清理,那么,未被GC清理的数据对象实例,我们称它为幸存者。

此时,0代中的幸存者会被转移到1代中(想想上面提到1代存放的是哪类对象实例...);

那么,以此类推,长期/处处被使用的对象实例,就会从1代中转移到2代中;

因此,2代中存放的通常为静态或全局作用域或长期被使用到的对象实例。

六、GC是如何去确定要清理的对象实例?

GC在堆中生成各对象间的结构图,作为回收对象的依据,找出非活动的对象。

所有数据对象实例之间的关联引用关系,都会生成一个完整的结构图,一些不在结构图中的 或超出所在作用域的 或不再被继续使用的对象实例,被称为非活动对象。被视为GC要清理的对象。

准确的说:

  • 堆栈根
  • 垃圾回收句柄
  • 静态数据

七、手动GC垃圾回收

在某些不常见的情况下,强制回收可提高应用程序的性能。在此,可使用 GC.Collect 方法强制执行垃圾回收,从而诱导垃圾回收。

注意,是诱导,而不是即刻回收。

为了考虑到应用程序当前的稳定运行,执行GC.Collect并不一定马上产生效果,这里仅仅是一个触发,会去收集将要回收的对象,回收动作会在未来某个合适的时间段进行。(当然,也可以强制阻塞式回收,这里略过)

(思考一下:无用的实例=null,是否告知GC为可回收的对象?再GC.Collect()后的效果。)

关于 GC.Collect 方法的参数,会用到上面提到的概念及场景:

  • 对指定的代进行回收
  • 指定回收次数
  • 强制回收 或 择机回收
  • 阻塞式回收 或 后台线程回收
  • 压缩 或 清理

(阻塞式回收方式:都先停一停,先让我回收完)

当然,通常建议:0代,择机,后台回收(阻塞式风险太大,通常选择择机方式,具体自我考量)

八、内存堆中的弱引用

当应用程序正在执行使用的对象,GC是不可能回收的,那么,就认为应用程序对该对象具有强引用。

强引用:应用程序正在使用的对象实例,不能被GC回收。

弱引用:应用程序暂时没使用的对象实例,暂时可被GC定义为可回收的实例,在回收之前,也可被应用程序再次使用后变为强引用。

假设一个对象实例被GC清理后,后续又被再次用到的场景,就会重新创建对象实例,那如果这个对象实例又比较大,这样的频繁创建... ...

当然还有优化的空间,所以,弱引用优化了以上场景。

弱引用的优点:对于频繁创建的大实例,弱类型可以做到一次创建多次使用,避免大对象实例多次创建的性能消耗。

(对于小对象使用弱类型,所带来的对对象管理上的性能消耗,是否值得)

若要对某对象建立弱引用,使用要跟踪的对象实例创建 WeakReference。 然后将 Target 属性设置为该对象,将该对象的原始引用设置为 null。(参考官方文档)

也就是说:我们可以自定义控制哪些对象实例要不要暂时不被GC垃圾回收。

 九、多应用共享内存时的垃圾回收

当多个应用程序在一台主机同时运行时,对内存空间大小的分配,建议是灵活可变的,以达到各应用程序对内存利用的平衡及稳定性。

如果启用 gcTrimCommitOnLowMemory 设置,垃圾回收器会计算系统内存负载,并在负载达到 90% 时进入修整模式。除非负载下降到不到 85%,否则会一直处于修整模式。

如果条件允许,垃圾回收器可以决定 gcTrimCommitOnLowMemory 设置对当前应用没有帮助并忽略它。

如下启用 gcTrimCommitOnLowMemory 设置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <runtime>
        <gcTrimCommitOnLowMemory enabled="true"/>
    </runtime>
</configuration>

到此这篇关于.Net的GC垃圾回收原理及实现的文章就介绍到这了,更多相关.Net GC垃圾回收 内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • ASP.NET购物车实现过程详解

    这篇文章主要为大家详细介绍了ASP.NET购物车的实现过程,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22
  • .NET Core下使用Kafka的方法步骤

    这篇文章主要介绍了.NET Core下使用Kafka的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • 在ASP.NET 2.0中操作数据之七十二:调试存储过程

    在开发过程中,使用Visual Studio的断点调试功能可以很方便帮我们调试发现程序存在的错误,同样Visual Studio也支持对SQL Server里面的存储过程进行调试,下面就让我们看看具体的调试方法。...2021-09-22
  • Win10 IIS 安装.net 4.5的方法

    这篇文章主要介绍了Win10 IIS 安装及.net 4.5及Win10安装IIS并配置ASP.NET 4.0的方法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-22
  • 详解.NET Core 3.0 里新的JSON API

    这篇文章主要介绍了详解.NET Core 3.0 里新的JSON API,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • .net数据库操作框架SqlSugar的简单入门

    这篇文章主要介绍了.net数据库操作框架SqlSugar的简单入门,帮助大家更好的理解和学习使用.net技术,感兴趣的朋友可以了解下...2021-09-22
  • ASP.NET Core根据环境变量支持多个 appsettings.json配置文件

    这篇文章主要介绍了ASP.NET Core根据环境变量支持多个 appsettings.json配置文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • 记一次EFCore类型转换错误及解决方案

    这篇文章主要介绍了记一次EFCore类型转换错误及解决方案,帮助大家更好的理解和学习使用asp.net core,感兴趣的朋友可以了解下...2021-09-22
  • 详解ASP.NET Core 中基于工厂的中间件激活的实现方法

    这篇文章主要介绍了ASP.NET Core 中基于工厂的中间件激活的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-22
  • C#使用Ado.Net更新和添加数据到Excel表格的方法

    这篇文章主要介绍了C#使用Ado.Net更新和添加数据到Excel表格的方法,较为详细的分析了OLEDB的原理与使用技巧,可实现较为方便的操作Excel数据,需要的朋友可以参考下...2020-06-25
  • .NET C#利用ZXing生成、识别二维码/条形码

    ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口。这篇文章主要给大家介绍了.NET C#利用ZXing生成、识别二维码/条形码的方法,文中给出了详细的示例代码,有需要的朋友们可以参考借鉴。...2020-06-25
  • asp.net通过消息队列处理高并发请求(以抢小米手机为例)

    这篇文章主要介绍了asp.net通过消息队列处理高并发请求(以抢小米手机为例),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • ASP.NET单选按钮控件RadioButton常用属性和方法介绍

    RadioButton又称单选按钮,其在工具箱中的图标为 ,单选按钮通常成组出现,用于提供两个或多个互斥选项,即在一组单选钮中只能选择一个...2021-09-22
  • ASP.NET 2.0中的数据操作:使用两个DropDownList过滤的主/从报表

    在前面的指南中我们研究了如何显示一个简单的主/从报表, 该报表使用DropDownList和GridView控件, DropDownList填充类别,GridView显示选定类别的产品. 这类报表用于显示具有...2016-05-19
  • 详解.NET Core 使用HttpClient SSL请求出错的解决办法

    这篇文章主要介绍了.NET Core 使用HttpClient SSL请求出错的解决办法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2021-09-22
  • Python调用.NET库的方法步骤

    这篇文章主要介绍了Python调用.NET库的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-05-09
  • ASP.NET中iframe框架点击左边页面链接 右边显示链接页面内容

    这篇文章主要介绍了ASP.NET中iframe框架点击左边页面链接,右边显示链接页面内容的实现代码,感兴趣的小伙伴们可以参考一下...2021-09-22
  • 创建一个完整的ASP.NET Web API项目

    ASP.NET Web API具有与ASP.NET MVC类似的编程方式,ASP.NET Web API不仅仅具有一个完全独立的消息处理管道,而且这个管道比为ASP.NET MVC设计的管道更为复杂,功能也更为强大。下面创建一个简单的Web API项目,需要的朋友可以参考下...2021-09-22
  • ASP.NET连接MySql数据库的2个方法及示例

    这篇文章主要介绍了ASP.NET连接MySql数据库的2个方法及示例,使用的是MySQL官方组件和ODBC.NET,需要的朋友可以参考下...2021-09-22
  • Asp.Net使用Bulk实现批量插入数据

    这篇文章主要介绍了Asp.Net使用Bulk实现批量插入数据的方法,对于进行asp.net数据库程序设计非常有借鉴价值,需要的朋友可以参考下...2021-09-22