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

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

托管:可借助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 设置

1 <?xml version="1.0" encoding="UTF-8"?>
2 <configuration>
3 <runtime>
4 <gcTrimCommitOnLowMemory enabled="true"/>
5 </runtime>
6 </configuration>

.Net平台的GC垃圾回收的更多相关文章

  1. java面试题之----JVM架构和GC垃圾回收机制详解

    JVM架构和GC垃圾回收机制详解 jvm,jre,jdk三者之间的关系 JRE (Java Run Environment):JRE包含了java底层的类库,该类库是由c/c++编写实现的 JDK ( ...

  2. Java学习之二(线程(了解) JVM GC 垃圾回收)

    线程与进程(了解)→JVM→字节码→GC 一.程序 = 算法 + 数据结构(大佬) 二.程序 = 框架 + 业务逻辑(现实) 1.线程与进程.同步与异步 1.1进程是什么? 进程就是操作系统控制的基本 ...

  3. 数往知来C#之接口 值类型与引用类型 静态非静态 异常处理 GC垃圾回收 值类型引用类型内存分配<四>

    C# 基础接口篇 一.多态复习 使用个new来实现,使用virtual与override    -->new隐藏父类方法 根据当前类型,电泳对应的方法(成员)    -->override ...

  4. GC垃圾回收算法

    什么是GC垃圾回收呢.日常生活中我们去餐厅吃饭吃完饭,吃完饭走了餐具不用管,服务员在把餐具拿走,这是一种方式,服务员怎么知道他要来把餐具拿走呢,因为你走了,这个位置空了.服务员什么时候拿走餐具很重要, ...

  5. GC垃圾回收

    我们在开发需求的时候,可能很少关注到垃圾回收,因为我们绝大多数的时候都是使用的托管资源,托管资源的内存回收.net已经帮我们做了,但是.net的内存回收不是实时的,所以我们还是要关注下.net的垃圾回 ...

  6. JVM学习02:GC垃圾回收和内存分配

    JVM学习02:GC垃圾回收和内存分配 写在前面:本系列分享主要参考资料是  周志明老师的<深入理解Java虚拟机>第二版. GC垃圾回收和内存分配知识要点Xmind梳理 案例分析1-(G ...

  7. JVM和GC垃圾回收机制和内存分配

    JVM运行期间 线程共享 线程私有 线程共享: 方法区 堆方法区:存放可以共享数据,静态常量,类的共有方法属性字段等,可以共享的存在方法区. 堆:存放class对象 . 线程私有:本地方法栈 虚拟机栈 ...

  8. RPC调用与GC垃圾回收

    RPC调用 多个服务协同完成一次业务时,由于业务约束(如红包不符合使用条件.账户余额不足等).系统故障(如网络或系统超时或中断.数据库约束不满足等),都可能造成服务处理过程在任何一步无法继续,使数据处 ...

  9. Java虚拟机笔记(二):GC垃圾回收和对象的引用

    为什么要了解GC 我们都知道Java开发者在开发过程中是不需要关心对象的回收的,因为Java虚拟机的原因,它会自动回收那些失效的垃圾对象.那我们为什么还要去了解GC和内存分配呢? 答案很简单:当我们需 ...

随机推荐

  1. Web 前端 - 又不仅限于 Web 前端 - 协程锁问题

    前言 最近两天的 web 前端开发中,早前的锁实现 (自旋锁) 出现了一些不合理的现象,所以有了这片随笔 什么是协程锁?能点进这个博客的的你肯定是明白的,不明白的人根本搜不到我这随笔,不多做赘述. 一 ...

  2. [递推]C. 【例题3】数的划分

    C . [ 例 题 3 ] 数 的 划 分 C. [例题3]数的划分 C.[例题3]数的划分 题目描述 将整数 n n n 分成 k k k 份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例 ...

  3. JMeter5.4.1源码IDEA构建&二次开发(实战)

    JMeter5.4.1源码IDEA构建&二次开发(实战) 目录 JMeter5.4.1源码IDEA构建&二次开发(实战) 1.下载源码 2.导入IDEA 2.1 先设置Gradle目录 ...

  4. 吃透什么是KVM虚拟化

    概念: 云计算自从提出,一直没有一个明确而统一的定义.维基百科对云计算做了如下的描述:云计算是一种通过因特网以服务的方式提供动态可伸缩的虚拟化的资源的计算模式.美国国家标准与技术研究院( NIST)定 ...

  5. baystack(ret2one_gadget)

    babystack 首先检查一下保护 全保护开启,我们IDA分析一下. main函数很简单,首先第一个read明显存在漏洞,如果不是以 \n 结尾会存在栈中地址的泄漏. payload = 'A'*0 ...

  6. Kubernetes部署metrics-server提示健康检测报错500,简单解决方式

    为什么写? 最近有项目要用到HPA(Horizontal Pod Autoscaler)依赖了k8s的 metrics 指标才能做出自动缩扩容的动作,我这边用官方GitHub v0.4.2版本启动不起 ...

  7. 【Azure Developer】调用SDK的runPowerShellScript方法,在Azure VM中执行PowerShell脚本示例

    当需要通过代码的方式执行PowerShell脚本时,可以参考以下的示例. Azure SDK中提供了两个方法来执行PowerShell脚本 (SDK Source Code: https://gith ...

  8. 关于GWAS的质量控制步骤顺序疑问?不同指导不同文献的建议各不相同。

          事情是这样的,刚开始接触GWAS就一定会接触到数据质量控制这个东西.我们可以看到网络上各种各样的指导,都是分为individual quality control and snp quan ...

  9. Day 12_61_多线程的创建和启动(二)

    多线程的创建和启动 * 在java中实现多线程的第二种方法 实现java.lang.Runnable接口,重写run()方法 * 推荐使用这种方式,因为实现接口还可以保留类的继承. package c ...

  10. 03- 手机App功能测试要点以及登录页面的测试

    当你进入一个互联网公司以后,首先对公司结构有所了解,然后遇到问题找对应的工作人员,效率就事半功倍了. 公司的结构: 产品经理 项目经理 设计师 开发人员 测试人员 运维人员 运营人员 配置管理 App ...