说实话,这章描述得太糟糕了。基本上是在百度上度过了日子。
一、CLR的作用
不同的语言(VB.net、C#等)都有自己的功能块,自己的函数,类等,它们都可以自己用自己的。
但是,是不是各自为阵,浪费了大量的精力呢?比如求平方根,他们的目的都是一样的。于是产生一个节约的思想:
于是,用一个公共的库,不同的语言都可以来调用,这样不再各自设计自己的,节约了大量的精力。
这就是CLR产生的由来。
CLR是介于语言与操作系统之间:
要描述这样的公共库,都必须用同样的一种语言MSIL,它都可以被不同的语言识别,于是产生了:
CTS(公共类型系统) ,不同语言的类型最终转化成一套统一的公共类型。
比如,在VB6中调用API时,很麻烦,因为API是用C写的,C与VB6的类型不一样,传参数到API时,VB6中类型常考究很久。
有了这个CTS,你不再担心不同语言之间的麻烦。
CLS(公共言语规范),不同语言遵循的语言规范,这样被不同语言识别。
架设了统一的公共语言,并没有完事,最终形成的MSIL(中间语言),之所以叫中间语言,因为它还不是可执行的。
.net要经两次编译得到最终的可执行程序。第一次转为中间语言IL
第二次编译时,在目的计算机上安装后,当且仅当第一次运行进会发生第二次编译,最终就形成了可执行文件:
上面两次编译中都离不开CLR的大力支持。
二、各种概念
解决方案、项目、程序集、模块、元数据
元数据,就是说明数据的数据。因为IL以某形式打包时,别人无法来知道这是什么东西,产生了元数据来说明这些东西是什么。
正如,假定某项目是一本书,总得来说明,什么是章节、什么是目录,什么是书名,哪页有什么内容,这些说明就是元数据。
模块,就是某个功能块,来完成某逻辑功能的。它正如一本书中的某一章一样,单独介绍某些知识。
程序集,由多个模块来组成,并说明哪个是入口,模块之间的联系。正如一本书中由很多章来组成,并确定哪一章是第一章节(入口)
并有一个清单,来说明各章之间的关系,如果你是中级读者应该怎么来阅读章节一样。
项目,有点类同模块,但项目通常较为完整地完成一些功能。简单的说,《vb.net 程序入门》这本书可以是一个项目。
解决方案,和项目一样都是从逻辑上划分,比项目范围更大,比如解决方案是计算机专业,那么不仅是一本书《vb.net程序入门》来完成,还涉及
其它项目比如《高等数学》、《概率》等。
重点:
1、 解决方案可以只有一个项目。也可以有几个项目来组成。
2、解决方案可以只有一个程序集,也可以有几个程序集
3、程序集可以只有一个模块,也可以有几个模块,程序集与模块的区别就是是否有程序集清单,有就是程序集,否则是模块。
4、程序集可以有一个项目,也可以有几个项目
5、项目可以只有一个模块,也可以有几个项目。
三、GAC
全局程序集缓存,位置如图:
它是怎么产生的,有什么作用呢?
通俗地说,是为了升级管理用的,官方地说:版本化管理。为什么要有这个呢?
以前的一个程序里面有很多exe和dll,它们来自不同的厂商(或作者),比如播放器要用不同的解码。
如果一个程序升级了,附属的dll没有升级,就会创建兼容性问题(百度:Dll Hell)
以前的管理都是把这些附属的东西在注册表中注册登记,来管理这些版本问题。有些附属dll是共用的,一旦删除某程序附属的dll
也会导致另一个使用这个dll的程序崩溃。
为了解决上面矛盾,.net用了GAC,它使用一些方法来管理,比如同一程序允许支持不同版本的dll,对dll的版本进行限制(比如高于
某版本就不会运行)
四、GC
垃圾回收器,就是回收资源、释放内存的。
不确定性:无法确定它释放的时间,GC总是根据自己的算法来释放,比如:最新分配的优先于其它存在时间长的首先释放;内存不足时,启动GC回收。
原因:GC运行时很费资源,所以它只在认为必要时才自动进行回收(即使对象已经没有用了)
finalize: 释放非托管资源。比如对象中含有打开另一个文件的句柄,在释放对象时,用finalize先进行关闭这个句柄。
它有点象析构函数,在对象释放前做一些前期的辅助工作。
dispose: 释放托管或非托管资源资源
托管堆:本质上它就是C++中的堆(区别于栈),加上“托管”之意,它不是立即释放,而是被GC控制,释放时间具有不确定性。
它有一个顶端指针,下一个新的分配就从这个指针开始。当GC运行时,就会压缩它,使之排列紧密腾出较大空间。
如上,堆上有ABC三对象,指针在顶部(便于以后再分配定位),
当B不再被引用时,并没有立即回收。
当新的对象D分配时,根据指针在顶部分配即可。
当GC运行时,向下压缩紧密即可,就腾出较大空间。(这时,原来的B才真正的释放了)