.NET Framework 程序的运行原理

.NET Framework的组成:
(1)基础类库(BCL):使用线程的类来完成编程,对于不存在的类,就自己编写;
(2)编译工具:将源文件,编译成“程序集”(exe或dll等)[.NET环境中,MSIL=CIL=IL]
(3)公共语言运行时(CLR):执行前检测、编译;执行到了某个方法时才编译这个方法的代码[即时编译器(JIT)]
编译过程:.NET源代码(C#)——>通过C#编译器编译成程序集[程序集中包括:元数据(一个表,显示了程序中有什么成员,类,字段,方法等),IL代码等资源]
运行例子:
(1)源代码如下:
using System;

namespace SimpleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            Console.WriteLine("ByeBye World!");
        }
    }
}
——>程序都是从上到下执行,执行Main方法前要检查Main方法中有什么类,为类分配一个临时的内存空间表。该类(各个类)中每一个方法,都有一个对应的地址(此时地址还是空的)。
——>当执行到第一个Console.WriteLine时:CLR中的JIT找到对应的IL代码,并将其编译成机器码并优化,将编译好的代码放到内存块中,会产生一地址,例如:0x000100
——>开始执行该WriteLine方法实体——>第二次执行WriteLine时:CLR会检查之前的方法表,如果已经存在地址,则不再编译执行。
内存分配:
线程栈:数据地址从高位向低位存放;
托管堆:数据地址从低位向高位存放;
.NET Framework 垃圾回收机制 GC

GC(Garbage Collection)垃圾收集,指的是在.net中垃圾内存收集的机制。

GC原理:当代码创建的时候,对象在内存中“连续”分配;当执行一次垃圾回收以后,失去引用的对象将会被释放;而保持引用的对象会重新“排序”(0代->1代)[重新排序后内存依旧是连续的]

以下是转载自轩脉刃de刀光剑影的博客 原文地址: http://www.cnblogs.com/yjf512/archive/2010/09/14/1825518.html

首先要了解的几点:

  1. 在.net中,托管代码的内存管理是自动的,由GC进行管理。但是对于非托管代码,.net就无法自动管理了。
  2. CLR运行时候,内存分为“托管堆”和“栈”两个部分。其中,栈是用于存储值类型的数据,托管堆是用于存储引用类型的变量。其中托管堆是GC处理的内存部分。
  3. 进程中每个线程都有自己的堆栈。

对于托管代码的GC原理解读:

垃圾判定:

回收垃圾首先要知道什么是垃圾,一个变量如果在其生存期内的某一时刻已经不再被引用,那么,这个对象就有可能成为垃圾。

public static void Main()
              {
                 string sGarbage = "I'm here";
           //下面的代码没有再引用s,它已经成为垃圾对象---当然,这样的代码本身也是垃圾;
            //此时如果执行垃圾收集,则sGarbage可能已经魂归西天
                  Console.WriteLine("Main() is end");
              }

对象代龄:

GC认为,越晚创建的对象越短命,所以,其引入一个“代龄”的概念来划分对象生存级别

这个代龄划分机制简要来说是一代新人换旧人:

CLR初始化后的第一批被创建的对象被列为0代对象。CLR会为0代对象设定一个容量限制,当创建的对象大小超过这个设定的容量上限时,GC就会开始工作,工作的范围是0代对象所处的内存区域,然后开始搜寻垃圾对象,并释放内存。当GC工作结束后,幸存的对象将被列为第1代对象而保留在第1代对象的区域内。此后新创建的对象将被列为新的一批0代对象,直到0代的内存区域再次被填满,然后会针对0代对象区域进行新一轮的垃圾收集,之后这些0代对象又会列为第1代对象,并入第1代区域内。第1代区域起初也会被设上一个容量限制值,等到第1代对象大小超过了这个限制之后,GC就会扩大战场,对第1代区域也做一次垃圾收集,之后,又一次幸存下来的对象将会提升一个代龄,成为第2代对象。

可见,有一些对象虽然符合垃圾的所有条件,但它们如果是第1代(甚至是第2代老臣)对象,并且第1代的分配量还小于被设定的限制值时,这些垃圾对象就不会被GC发现,并且可以继续存活下去。

对于非托管代码,GC不能自动收集垃圾,需要的方法有两种:1,重写让GC自动调用的Finalize方法。 2,实现IDispose提供给我们显示调用的方法Dispose()

  1. Finalize

~ClassName() {//释放你的非托管资源}

Finalize是由GC负责调用,是一种自动释放的方式。

问:为什么说实现了Finalize方法的对象必需等两次GC才能被完全释放?

Msdn中的解释:实现 Finalize 方法或析构函数对性能可能会有负面影响,因此应避免不必要地使用它们。用 Finalize 方法回收对象使用的内存需要至少两次垃圾回收。当垃圾回收器执行回收时,它只回收没有终结器的不可访问对象的内存。这时,它不能回收具有终结器的不可访问对象。它改为将这些对象的项从终止队列中移除并将它们放置在标为准备终止的对象列表中。该列表中的项指向托管堆中准备被调用其终止代码的对象。垃圾回收器为此列表中的对象调用 Finalize 方法,然后,将这些项从列表中移除。后来的垃圾回收将确定终止的对象确实是垃圾,因为标为准备终止对象的列表中的项不再指向它们。在后来的垃圾回收中,实际上回收了对象的内存。

第一次的GC做的事情是:1将有终结器的对象放到准备终结列表中,并执行Finalize方法。2 实际删除对象内存。

  1. Dispose

Dispose是提供给我们显示调用的方法。由于对Dispose的实现很容易出现问题,所以在一些书籍上(如《Effective C#》和《Applied Microsoft.Net Framework Programming》)给出了一个特定的实现模式:

class DisposePattern :IDisposable
    {
        private System.IO.FileStream fs = new System.IO.FileStream("test.txt", System.IO.FileMode.Create);

~DisposePattern()
        {
            Dispose(false);
        }

IDisposable Members#region IDisposable Members

public void Dispose()
        {
            //告诉GC不需要再调用Finalize方法,
            //因为资源已经被显示清理
            GC.SupdivssFinalize(this);

Dispose(true);
        }

#endregion
               
        protected virtual void Dispose(bool disposing)
        {
            //由于Dispose方法可能被多线程调用,
            //所以加锁以确保线程安全
            lock (this)
            {
                if (disposing)
                {
                    //说明对象的Finalize方法并没有被执行,
                    //在这里可以安全的引用其他实现了Finalize方法的对象
                }

if (fs != null)
                {
                    fs.Dispose();
                    fs = null; //标识资源已经清理,避免多次释放
                }
            }
        }
    }

注: 关键字using()中包含的变量就需要实现了IDispose借口,当出了using的范围的时候会自动使用Dispose方法。

转载于:https://www.cnblogs.com/edisonchou/archive/2012/07/05/2577555.html

黑马公开课——运行原理与GC学习笔记相关推荐

  1. 麻省理工公开课《算法导论》学习笔记:第一讲

    主题:简介课程,渐近概念的大局观,插入排序和归并排序,递归式函数时间分析(递归树方法) 教材:<算法导论> 收获:很感动地看到算法分析那个log(n)是为什么出现了,更深层还要听第二讲,若 ...

  2. 中国大学慕课公开课-《视听语言》-学习笔记-5

    目录 第六章-摄影元素构成 6.1-影像的构成 6.2-影像语言的画面构成-背景 6.3-影像语言的画面构成-陪体 6.4-影像语言的画面构成-前景 第六章-摄影元素构成 6.1-影像的构成 影像的构 ...

  3. 中国大学慕课公开课-《视听语言》-学习笔记-6

    目录 第7章-摄影创作角度 7.1-影像语言的画面构成-色调 7.2-影像语言的画面构成-线条 7.3-影像的角度选择-大远景和远景 7.4-影像的角度选择-大全景.全景和中景 7.5-影像的角度选择 ...

  4. 中国大学慕课公开课-《视听语言》-学习笔记-4

    目录 第五章-用光 5.1-正面光与侧面光 5.2-侧光与侧逆光 5.3-逆光 5.4-顶光与底光 第五章-用光 5.1-正面光与侧面光 光线的属性 光线类别 自然光:户外纪实 人造光:影视广告 光的 ...

  5. 中国大学慕课公开课-《视听语言》-学习笔记-2

    目录 3-机身系列 3.1-照相机机身结构 3.2-快门的造型作用 3.3-照相机的基本类型 3.4-摄像机的结构类型 3-机身系列 3.1-照相机机身结构 机身的结构:功能性的体现 照相机的机身 快 ...

  6. 非常详细GC学习笔记

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! GC学习 ...

  7. 2019微信公开课Pro微信之夜内容笔记总结

    2019微信公开课Pro 微信之夜内容笔记总结 小程序入口 我的小程序 任务栏入口 线下扫码 搜索小程序 附近小程序升级 用户留存问题 小程序成长 关注用户需求 性能监控 广告主&&流 ...

  8. Unix原理与应用学习笔记----第六章 文件的基本属性2

    Unix原理与应用学习笔记----第六章 文件的基本属性2 改变文件权限命令:chmod 提示:文件或目录创建后,就被赋予一组默认的权限.所有的用户都有读,只有文件的所有者才有写. 相对权限设置 Ch ...

  9. 公开课计算机原理,《计算机的基本工作原理》公开课材料

    <<计算机的基本工作原理>公开课材料>由会员分享,可在线阅读,更多相关<<计算机的基本工作原理>公开课材料(11页珍藏版)>请在人人文库网上搜索. 1. ...

最新文章

  1. robotium常用方法
  2. php 进制 小数,小数进制转换
  3. Android Fragment应用实战
  4. 12-factor应用和微服务架构应用的区别
  5. C#InI文件读写剖析
  6. Flexible 弹性盒子模型之CSS align-items 属性
  7. 【原】docker部署单节点consul
  8. Mybatis一二级缓存的理解
  9. Linux学习笔记---移植官方linux步骤(一)
  10. 【资源】About Face4交互设计精髓,英文原版,彩色pdf下载
  11. C++独立游戏存档模块设计
  12. 四路模拟高清解码,CVI,四通道多合一同轴高清解码芯片方案
  13. php图片虚化处理 api PHP实现生成模糊图片
  14. 初中英语语法(006)-特殊疑问句·祈使句·感叹句
  15. axure 折线图部件_Axure教程:折线图
  16. 微信群聊在哪个服务器,咱们谈谈微信群,为什么很多的聊天群变得越来越冷漠了...
  17. Spring3开发实战 之 第二章:IoC/DI开发(2)
  18. 如何让USB-C手机,电脑投屏到VR眼镜方案?还能同时实现充电?乐得瑞LDR6282 转接器方案
  19. android 传感器小游戏,重力感应球游戏
  20. w3c关于Html的标准

热门文章

  1. 洛谷P1494 [国家集训队]小Z的袜子
  2. Linux CA证书与https讲解
  3. 漫谈惯性、视觉暂留、潜意识、混合动力发动机、先入为主 - 纯粹的无厘头?...
  4. Android调用系统照相机
  5. C#操作Sqlite快速入门及相关工具收集(连接串管用)
  6. 什么是数据的表分区(文章附上Server 2005分区实施方案)
  7. python代替嵌套列表_python含嵌套的列表去重问题
  8. rust模组服如何切换标准服_资讯DNF手游将于3月20日发放10000个体验服资格(附申请方法)...
  9. mysql 表与表之间的条件比对_《MySQL数据库》关联查询
  10. DataStorage分析