CLR via C# 笔记 -- 托管堆和垃圾回收(21)
1. 访问一个资源所需的步骤
1). 调用IL指令newobj,为代表资源的类型分配内存(一般使用C# new 操作符来完成)。
2). 初始化内存,设置资源的初始状态并使资源可用。类型的实例构造器负责设置初始状态。
3). 访问类型的成员来使用资源(有必要可以重复)。
4). 摧毁资源的状态以进行清理。
5). 释放内存。垃圾回收器独自负责这一步。
分配并初始化资源并直接使用。大多数类型都无需资源清理,垃圾回收器会自动释放内存。
2. 从托管堆分配资源
CLR 要求所有对象都从托管堆分配。进程初始化时,CLR划出一个地址空间区域作为托管堆。CLR还要维护一个指针,我把它称作NextObjPtr。该指针指向下一个对象在堆中的分配位置。
一个区域被非垃圾对象填满后,CLR会分配更多区域。这个过程一直重复,直到整个进程地址空间被填满。所以,你的应用程序的内存受进程的虚拟地址空间的限制。32位进程最多能分配1.5GB,64位进程最多能分配8T。
3. new操作符导致CLR执行以下步骤
1). 计算类型的字段(以及从基类型继承的字段)所需的字节数
2). 加上对象的开销所需的字节数。每个对象都有两个开销字段:类型对象指针和同步块索引。对于32位应用程序,这两个字段各自需要32位,所以每个对象要增加8个字节。对于64位应用程序,这两个字段各自需要64位,所以每个对象要增加16个字节。
3). CLR检查区域中是否有分配对象所需的字节数。如果托管堆有足够的可用空间,就在NextObjPtr指针指向的地址处放入对象,为对象分配的字节会被清理。接着调用类型的构造器(为this参数传递NextObjPrt),new操作符返回对象引用。就在返回这个引用之前,NextObjPrt指针的值会加上对象占用的字节数得到一个新值,即下个对象放入托管堆时的地址。
4. 垃圾回收算法。应用程序调用new操作符创建对象时,如果第0代没有只够的地址空间来分配对象,CLR就执行垃圾回收。
引用追踪法:CLR开始GC时,首先暂停进程中的所有线程。这样可以防止线程在CLR检查期间访问对象并更改其状态。然后,CLR进入GC的标记阶段。在这个阶段,CLR便利堆中的所有对象,将同步块索引字段中的一位设为0,这表明所有对象都应删除。然后,CLR检查所有活动的根,查看它们引用了哪些对象。如果根引用了堆上对象,则将同步块索引字段中的一位设为1。检查完毕后,未标记的会被删除,已标记的会被转移,并从每个根减去所引用的对象的内存中偏移的字节数。
静态字段应用一直存在,直到用于加载类型的AppDomain卸载为止(考虑内存泄漏)。
5. GC是基于代的垃圾回收器。共有第0代,第1代和第2代。第0代对象就是那些新构造的对象。CLR初始化时为第0代对象选择一个预算容量(以KB为单位)。如果分配一个新对象造成第0代超过预算,就启用一次垃圾回收,垃圾回收中存活的对象现在成为第1代,第0代不再包含任何对象。第2代同理。预算是根据回收量动态调节的
6. 触发GC的条件
1). 第0代超预算时
2). 显示调用GC.Collect方法
3). window报告低内存情况,通过 CreateMemoryResourceNotification 和 QueryMemoryResourceNotification监视系统总体内存使用情况
4). AppDomain卸载时
7. 大对象。超过85000字节或更大的对象。
1). 大对象不是在小对象的地址空间分配,而是在进程地址空间的其他地方分配的。
2). 目前版本GC不压缩大对象,可能会造成碎片化。
3). 大对象总是2代。不可能是 1代或0代。只能为长时间存活的资源创建大对象。
8. GC模式
1). 工作站:默认值;该模式针对客户端应用程序优化GC。GC造成的延时成本很低,应用程序线程挂起时间很短,避免使用户感到焦虑。
2). 服务器:该模式针对服务器端应用程序优化GC。被优化的主要是吞吐量和资源利用。GC假定机器上没有运行其他应用程序,并假定机器的所有CPU都可用来辅助完成GC。该模式造成托管堆被拆分成几个区域,每个CPU一个。开始垃圾回收时,垃圾回收器在每个CPU上都运行一个特殊线程;每个线程都和其他线程并发回收它自己的区域。对于工作者线程(worker thread)行为一致的服务器应用程序,并发回收能很好的进行。
9. Finaliize 方法。被视为垃圾的对象在垃圾回收完毕后才调用Finalize方法,所以这些对象的内存不是马上被回收,因为Finalize方法可能要执行访问字段的代码。可终结对象在回收时必须存活,造成它被提升到另一代,使对象活的时间比正常的长。
CLR via C# 笔记 -- 托管堆和垃圾回收(21)的更多相关文章
- C#托管堆和垃圾回收
垃圾回收 值类型 每次使用都有对应新的线程栈 用完自动释放 引用类型 全局公用一个堆 因此需要垃圾回收 操作系统 内存是链式分配 CLR 内存连续分配(数组) 要求所有对象从 托管堆分配 GC 触发条 ...
- CLR via C# 读书笔记-21.托管堆和垃圾回收
前言 近段时间工作需要用到了这块知识,遂加急补了一下基础,CLR中这一章节反复看了好多遍,得知一二,便记录下来,给自己做一个学习记录,也希望不对地方能够得到补充指点. 1,.托管代码和非托管代码的区别 ...
- 【CLR】解析CLR的托管堆和垃圾回收
目录结构: contents structure [+] 为什么使用托管堆 从托管堆中分配资源 托管堆中的垃圾回收 垃圾回收算法 代 垃圾回收模式 垃圾回收触发条件 强制垃圾回收 监视内存 对包装了本 ...
- 重温CLR(十五) 托管堆和垃圾回收
本章要讨论托管应用程序如何构造新对象,托管堆如何控制这些对象的生存期,以及如何回收这些对象的内存.简单地说,本章要解释clr中的垃圾回收期是如何工作的,还要解释相关的性能问题.另外,本章讨论了如何设计 ...
- 【C#进阶系列】21 托管堆和垃圾回收
托管堆基础 一般创建一个对象就是通过调用IL指令newobj分配内存,然后初始化内存,也就是实例构造器时做这个事. 然后在使用完对象后,摧毁资源的状态以进行清理,然后由垃圾回收器来释放内存. 托管堆除 ...
- .NET 托管堆和垃圾回收
托管堆基础 简述:每个程序都要使用这样或那样的资源,包括文件.内存缓冲区.屏幕空间.网络连接.....事实上,在面向对象的环境中,每个类型都代表可供程序使用的一种资源.要使用这些资源,必须为代表 ...
- 托管堆和垃圾回收(GC)
一.基础 首先,为了深入了解垃圾回收(GC),我们要了解一些基础知识: CLR:Common Language Runtime,即公共语言运行时,是一个可由多种面向CLR的编程语言使用的"运 ...
- cir from c# 托管堆和垃圾回收
1,托管堆基础 调用IL的newobj 为资源分配内存 初始化内存,设置其初始状态并使资源可用.类型的实列构造器负责设置初始化状态 访问类型的成员来使用资源 摧毁状态进行清理 释放内存//垃圾回收期负 ...
- 如何管好.net的内存(托管堆和垃圾回收)
一:C#标准Dispose模式的实现 需要明确一下C#程序(或者说.NET)中的资源.简单的说来,C#中的每一个类型都代表一种资源,而资源又分为两类: 托管资源:由CLR管理分配和释放的资源,即由CL ...
- C# 托管堆和垃圾回收器GC
这里我们讨论的两个东西:托管堆和垃圾回收器,前者是负责创建对象并控制这些对象的生存周期,后者负责回收这些对象. 一.托管堆分配资源 CLR要求所有的对象都从托管堆分配.进程初始化时,CLR划出一个地址 ...
随机推荐
- 2019-7-3-Roslyn-理解-msbuild-的清理过程
title author date CreateTime categories Roslyn 理解 msbuild 的清理过程 lindexi 2019-07-03 18:21:25 +0800 20 ...
- 让 KEPServer 变成一款 Web 组态软件
KEPServerEX是行业领先的连接平台,用于向您的所有应用程序提供单一来源的工业自动化数据.该平台的设计使用户能够通过一个直观的用户界面来连接.管理.监视和控制不同的自动化设备和软件应用程序. ...
- Java开启异步的两种方式
二.Java开启异步的两种方式 1.注解开启:@Async 1.1.配置异步的线程池 必须配置异步线程池,否则异步不会生效. @EnableAsync 注解:指定异步线程池.不指定默认使用:Simpl ...
- selenium项目中遇到的问题总结
问题:在pycharm中运行用例能成功,在命令行运行提示找不到com包解决办法:添加一个PYTHONPATH的环境变量,值为工程目录的路径 当要查找的文本前后有换行时,用如下方法解决//td[cont ...
- 茴香豆 RAG 平台实操-书生浦语大模型实战营第二期第3节作业
书生浦语大模型实战营第二期第3节作业 本页面包括实战营第二期第三节作业的全部操作步骤.如果需要知道RAG相关知识请访问学习笔记. 作业要求 基础作业 在茴香豆 Web 版中创建自己领域的知识问答助手 ...
- DP-Modeler软件初步教程1:数据文件导入
1.导入航拍影像的空三文件 先打开DPSlnManager.exe软件,DP数据管理是用这个软件来操作的. 先从CC中导出空间文件,XML格式和无损影像.然后导入到DP 2.从CC中导出OSGB,然 ...
- UE4 C++调用C# DLL(DllExport方法)
之前看见园子里一篇C++调用C#的文章,参考后拿UE试一下.刚开始尝试了C# dll > CLR C++ DLL > Native C++ DLL的做法, 原生环境下是可以的,但是到UE4 ...
- JDK8之前,匿名内部类访问的局部变量为什么必须要用final修饰
更多博文请关注:https://blog.bigcoder.cn 前不久在学习中意外发现了自己原来忽略的一个小知识点,挺有意思的,现在我来给大家分享一下! 我们先来看一段代码 public class ...
- django中的多表关联
一.三种关联情况 二.ORM的正向操作和反向操作 1.正向操作: 一个模型中定义了一个外键,通过该模型对该外键操作的操作叫做正向操作. 2.反向操作: 被外键所关联的模型,通过该模型对外键所在模型的操 ...
- jQuery实现简单的模态框
<!-- jquery模态框 --> <!DOCTYPE html> <html lang="en"> <head> <met ...