C#.Net学习笔记——CLR核心机制

一、CLR基本介绍

(1)C(Common) L(Language) R(Runtime) IL的运行环境

(2)从下图可以看到,我们的计算机会先把我们写的语言,编写成IL语言,再给计算机去读取。为什么我们不直接把我们的语言编写成计算机能够读取的?主要是考虑到我们计算机的不同,比如32位和64位,他们接收到计算机指令都是不一样的。甚至在不同的操作环境下得出的结果也是不一样的。因此,我们就需要有一个中间语言ILCLR(通用语言进行时)就是IL的运行环境。

(3)metadata清单数据,里面是描述了dll或者exe内有什么东西,依赖了什么东西。

(4)Exe文件的运行。实际上我们的exe文件可以运行,都是由CLR完成的,它为我们加载exe,检查metadata清单和IL。最后JIT(运行时编译)会交给计算机去执行。所以说CLR本质上可以说是一个IL的运行环境。

(5)编译器只要满足CLS规范,编译出来的东西就可以转换成IL语法

(6)使用CLR需要安装.Net Framework

、堆栈内存分配

(1)基本介绍

什么内存?        程序运行时,进程占有的内存

谁来分配?        CLR来分配

1、值类型:struct  枚举

2、引用类型:class  接口  委托

线程栈:栈-stack 先进后出的数据结构,随着线程而分配的,默认执行方法分配1M内存

对象堆:内存,进程中独立画出来的一块内存,有一些对象是不释放的,有些对象需要重用的。类似这种我们就需要堆空间。

 (2)关于Struct 

通过反编译我们可以看到,struct在中间语言里实际上也是class,但是它继承了父类System.ValueType。也就是说,只要是继承了ValueType的,我们就可以认为是值类型

1、对于结构体,我们可以把它当作一个变量直接声明,也可以通过构造函数的方式new出来(结构体的构造函数必须包含所有字段和属性),但是无论哪种方式它都是值类型

  (3)关于Class

引用类型分布在堆上面,变量(左边)是在栈上的,值(右边)是在堆上的

1、new的时候去堆开辟内存,分配一个地址

2、调用构造函数(因为在构造函数里可以使用this),才执行构造函数

3、把引用传给变量

问题思考:

我们有一个类(ReferenceTypeClass),这个类有一个字段int valueTypeField和一个方法Method,方法Method内又声明了一个int valueTypeLocalVariable类型的字段。请问ValueTypeFieldValueTypeLocalVariable分别位于堆还是栈?

答案:valueTypeField是位于堆里,valueTypeLocalVariable是位于栈里。

因为对象都在堆里,那么对象里面的属性也在堆里。而方法内声明的变量是在栈里,当调用我们的方法的时候,线程栈会给声明一个临时变量,是一个全新的局部变量。

总结:方法的局部变量:根据变量自身决定,跟所在环境没关系

           对象是引用类型,其属性/字段都在堆里面

           对象是值类型,其属性/字段,值类型就在栈里,引用类型就在堆里。

引用类型任何时候都在堆里;值类型都在栈里,除非值类型所在对象是在堆里。

、拆箱装箱(浪费性能)

1、装箱:值类型->引用类型

int i = 3;
object Value = i;

2、拆箱:引用类型->值类型

object Value = 10;
int k = (int)Value;

3、拆箱装箱只能发生在父子类里面?因为这样才能转换。

四、特别对象——字符串

1、string是一个引用类型

思考1:string是一个引用类型,下面例子中声明了一个student和student2。student2=student,使得他们指向同一内存 “哈哈” 。但是为什么在student2赋新值后student不会跟着改变。

   private void button17_Click(object sender, EventArgs e){string student = "哈哈";string student2 = student;Log.Info(student + " " + student2);student2 = "1234";Log.Info(student + " " + student2);}

答案:因为赋值其实new了一个新的string,重新开辟内存,返回引用。

        改了student2的值,但不是修改内存;string字符串的内存是不可变的

思考2:看案例,student和student2都是指向不同的内存,当我们重新给studeng2赋值并且这个值与student的值相等。按照上面的理论,他们的指向应该都是各自的内存,只不过他们的值恰好相等。思考一下他们都指向哪?

        private void button17_Click(object sender, EventArgs e){string student = "哈哈";string student2 = "呵呵";student2 = "哈哈";Log.Info(object.ReferenceEquals(student, student2));}

答案:实际上他们还是指向了同一片内存。这就是我们CLR的机制,CLR内存分配字符串的时候,会查找相同值,有就重用。因此他们会指向相同内存以节约内存。

不可变是因为享元,可能有多个变量指向同一字符串,字符串变化了,多个变量都会受影响。

还因为堆里面的内存是连续分配的,如果变长度,会导致大量数据的移动。所以不如重新分配一个。

五、垃圾回收

(1)产生垃圾的原因:

1、值类型出现在线程栈:用完自己就结束,变量-值类型都会释放的。

2、引用类型出现在堆里:全局就一个堆,空间有限,所以才需要垃圾回收。

3、操作系统里面,内存是链式分配的,可能有碎片

4、CLR堆里边:连续分配(数组),空间有限,节约空间

(2)GC发生时机:

1、GC发生在New的时候,New一个对象时,会开辟内存在堆里边

2、New的时候看看空间够不够,不够的话就要GC了

3、定时程序,24小时执行一次,但是对象不会被回收,因为24小时之后你才会new,这个才能发生GC

4、静态不可能被回收 静态持有的引用也不会被回收

5、类似于下图这种情况,我们写了一个方法,方法内声明了Student和Class和一个int类型的变量。当方法执行结束后,值类型的i就会被直接回收,而引用类型的new Class则丢失引用,但是内存不会被自动回收,产生GC。

     private static Student _student = new Student(){Id = 1,Name = "Test",};public static void Show(){Student student = _student;Class @class = new Class(){Id = 1,CLassName = "Test",};int i = 3;  //会被GC}

6、主动GC

GC.Collect();

怎么回收?

什么是垃圾?垃圾是完全访问不到的东西

new的时候发现内存不够了,就去遍历所有堆的对象,标记访问不到,然后启动一个线程来清理内存。

移除标记了的对象,其他挪动,然后整齐摆放,所有这个时候全部线程停止,不允许操作内存。

为了促进垃圾回收,把对象赋值成null。其实不对,没有意义,垃圾回收是因为访问不到

 六、优化策略

1、首次GC前,全部对象都是0级。

2、第一次GC后,还保留的对象叫1级

3、回收先找1级对象,如果空间还不够,再去找1级对象,这之后,还存在的对象变成2级,2级还不够就内存溢出了

4、越是最近分配的,越是会被回收。比如for循环创建对象

因为回收过了,之前的内存可能是常驻内存,所以就从最近开始回收。

  七、析构函数

1、~Student 析构函数是用来释放非托管资源的,等着GC的时候去把非托管资源释放掉,系统自动执行。非托管资源就是管理不到的一些资源,包括数据库连接、打开的文档等。

 八、Using

1、下面可以说是等同关系,Using本质上来说只是一种语法糖

using(Student student = new Student())
{Id = 234
}
try
{Student student = new Student(){Id=234}
}
finally
{//调用的dispose()
}

2、Dispose() 主动释放,方法本身是没有意义的,我们需要在方法里面实现堆资源的释放

     而不是说对象释放的时候会自动去调用Dispose方法。

3、GC不会调用,而是用对象时,使用者主动调用这个方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/233974.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

21、Kubernetes核心技术 - 高可用集群搭建(kubeadm+keepalived+haproxy)

目录 一、简介 二、高可用集群架构说明 三、部署环境说明 四、高可用集群搭建 (1)、初始化所有节点 (2)、修改host文件 (3)、调整内核参数 (4)、所有节点安装Docker (4-1)、配置 docker 的阿里 yum 源 (4-2)、yum 安装 docker (4-3)、配置 docker 的镜像源 (4-4)…

攀登者2 - 华为OD统一考试

OD统一考试 分值: 200分 题解: Java / Python / C++ 题目描述 攀登者喜欢寻找各种地图,并且尝试攀登到最高的山峰。 地图表示为一维数组,数组的索引代表水平位置,数组的元素代表相对海拔高度。其中数组元素0代表地面。 例如:[0,1,2,4,3,1,0,0,1,2,3,1,2,1,0],代表如下…

win10录音功能大盘点,帮你轻松搞定录音

“有人知道win10系统怎么录音吗?在网上找到了一段英语听力,本来打算保存下来,但是发现不能下载,我也不会使用电脑录音,真的很头疼,有人能帮帮我吗。” 在Windows 10系统中,录音是一项常见但往往…

计算机网络学习笔记(四)

文章目录 1.介绍一下HTTPS的流程。2.介绍一下HTTP的失败码。3.说一说你知道的http状态码。4. 301和302有什么区别?5.302和304有什么区别?6. 请描述一次完整的HTTP请求的过程。7.什么是重定向?8. 重定向和请求转发有什么区别?9.介绍…

04 帧 Frame

文章目录 04 帧 Frame4.1 相机相关信息4.2 特征点提取4.2.1 特征点提取 ExtractORB()4.3 ORB-SLAM2对双目/RGBD特征点的预处理4.3.1 双目视差公式4.3.2 双目图像特征点匹配 ComputeStereoMatches()4.3.3 根据深度信息构造虚拟右目图像:ComputeStereoFromRGBD() 4.4 …

书生·浦语大模型全链路开源体系 学习笔记 第二课

基础作业: 使用 InternLM-Chat-7B 模型生成 300 字的小故事(需截图)。熟悉 hugging face 下载功能,使用 huggingface_hub python 包,下载 InternLM-20B 的 config.json 文件到本地(需截图下载过程&#xf…

Dijkstra算法——邻接矩阵实现+路径记录

本文是在下面这篇文章的基础上做了一些补充,增加了路径记录的功能。具体Dijkstra的实现过程可以参考下面的这篇文章。 [jarvan:Dijkstra算法详解 通俗易懂](Dijkstra算法详解 通俗易懂 - jarvan的文章 - 知乎 https://zhuanlan.zhihu.com/p/338414118) …

谷歌提出「边界注意力」模型,实现超越像素级检测精度!微弱边界也逃不过

有些情况下,当面临分辨率较低的图像时,可能会在进行诸如目标检测和图像分割等任务时遇到一些挑战和阻碍。这是因为低分辨率图像可能丢失了细节信息,使得计算机视觉系统难以准确捕捉和理解图像中的关键特征。在这种背景下,传统的方…

教程:Centos6迁移旧虚拟机文件后的网络配置教程,完美解决虚拟机移动后的网络ip变化问题

博主在工作后,想整整之前大学的虚拟机集群,因此特意从之前的旧电脑把虚拟机文件给拷贝了过来,在导入到vm-workstation,顺便能启动虚拟机后,发现之前的静态ip已经跟现在的宿主机网络不一样。想着重新配置,但觉得太麻烦,故想到了修改网卡的mac地址+网卡重配置方法,完美解…

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -后端架构搭建

锋哥原创的uniapp微信小程序投票系统实战: uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…

普中STM32-PZ6806L开发板(有点悲伤的故事续-人灯还未了)

简介 继上篇 普中STM32-PZ6806L开发板(有点悲伤的故事) 说到 关于 普中STM32-PZ6806L开发板的LED流水灯也被烧坏掉了,再也无法玩流水灯, 内心充满了只会流水灯的不甘, 流水灯就是单片机的Hello World,怎么能没有呢? 事情发展 好巧不巧想起最近…

报错解决:RuntimeError: Error building extension ‘bias_act_plugin‘

系统: Ubuntu22.04, nvcc -V:11.8 , torch:2.0.0cu118 一:BUG内容 运行stylegan项目的train.py时遇到报错👇 Setting up PyTorch plugin "bias_act_plugin"... Failed! /home/m…

【linux】tcpdump 使用

tcpdump 是一个强大的网络分析工具,可以在 UNIX 和类 UNIX 系统上使用,用于捕获和分析网络流量。它允许用户截取和显示发送或接收过网络的 TCP/IP 和其他数据包。 一、安装 tcpdump 通常是默认安装在大多数 Linux 发行版中的。如果未安装,可…

每天刷两道题——第十天

1.1和为k的子数组 给你一个整数数组 n u m s nums nums 和一个整数 k k k ,请你统计并返回 该数组中和为 k k k 的子数组的个数 。子数组是数组中元素的连续非空序列。 输入:nums [1,2,3], k 3 输出:2 前缀和 1.2如何使用 前缀和的…

Jmeter扩展函数?年薪50W+的测试大佬教你怎么玩

很多同学,都问我:“老师,我的 jmeter 里面,怎么没有 MD5 函数,base64 函数也没有,我是不是用了假的 jmeter?” 前言 哈哈哈,不是的。jmeter 的函数,有自带函数和扩展函数…

pycharm调整漂亮的颜色主题

主题样式: 一、设置主题为白色 二、pycharm 如何设置字体颜色 打开pycharm编辑器,file > settings > editor > color scheme > python > 你也可以直接用我资源中的配置好的文件

汽车中的ECU、VCU、MCU、HCU

一、ECU是汽车电脑,刷汽车电脑可以提高动力,也可以减低动力,看需求。 简单原理如下。 1.汽车发动机运转由汽车电脑(即ECU)控制。 2.ECU控制发动机的进气量,喷油量,点火时间等,从而…

基础数据结构第九期 堆(数组+STL)

前言 堆是一种重要的数据结构,因此应该熟练掌握。 一、堆的基本概念 堆的基本: 堆的结构实际上是一棵完全二叉树,堆可以分为大根堆和小根堆 大根堆: 小根堆: 堆的储存: 若节点小标为i,则左子…

竞赛保研 基于深度学习的人脸性别年龄识别 - 图像识别 opencv

文章目录 0 前言1 课题描述2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程 4 具体实现4.1 预训练数据格式4.2 部分实现代码 5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 毕业设计…