CLR寄宿和应用程序域

  • Win实际上将CLR作为一个COM服务器实现在一个DLL,即为CLR定义了标准的COM接口,并为该接口和COM服务器分配一GUID,安装FrameWork时表示CLRCOM服务器被注册到注册表内.任何Win APP都可以寄宿CLR.
    • 一个PC可安装多个版本的CLR,但是只有一个版本(最新版本)MSCorEE.dll(判断创建何版本的CLR,CLR COM服务器在MSCorwks.dllMSCorSvr.dll)(64位上有两个:For 32B/For 64B).且其知道如何找到以前版本的CLR.宿主可以指定加载的CLR,但是MSCorEE可能加载不同的CLR.
    • CLRMSCoWks.dll中实现,其一个CLR版本一个(V1.0/V1.1/V2.0下都有).调用CorBindToRuntimeEx()可以在非托管上使用托管代码.
  • APP域.
    • 提供隔离性(各域拥有独立的内存地址).
      • 1)CLR COM Server初始化时,会创建一个默认APP,该域仅在进程终止时才被销毁.
      • 2)一个APP域中创建的对象不可被另一APP域直接访问.一个APP域可以被卸载,单独实施安全/配置策略.
      • 3)Win将每个APP都置于一个地址空间内,进程开销大,APP全托管,可以运行多个托管APP于一个WIN进程内.APP域可卸载单个AM.
    • 加载器堆:维护APP被访问过的类型记录,每个类型一个方法表,当方法被执行过后,则指向编译后的本地代码.
    • 线程和APP域无1:1关系.APP域为CLR特征,可能多个APP域运行于一个WIN进程内,所以线程可先运行A APP域的代码后再运行B APP域的代码.所以使用APPDomain.CurrentDomian来获取当前APP(而非Thread.GetDomain).
    • AppDomian.CreateDomian在同一WIN进程中创建APP,并赋予安全/配置策略.
    • 在新APP域内创建对象实例:CreateInstanceAndUnWrap(Str1,Str2),Str1为要加载的AM,Str2为实例的类型名.导致线程迁移至当前APP域并得到对象的引用. Str2的类型:1)派生自MarshakbyRefObject,按引用封装对象.在目的APP域的加载器堆内定义一代理类型(其使用原始类型的元数据定义),其有实例字段表示那个APP域有原始类型该如何查找.运行于新建APP域内2)派生至Object[Serializable],过程:CLR将对象的实例字段序列化为一字节数组后,Copy至目的APP(会强制加载;类型的AM到目的APP),之后反序列化(可能导致CLR加载类型所在AM),新建一Type对象,用反序列化的数据初始化之.
    • APP域卸载.
      • 1)挂起所有执行过托管代码的线程.
      • 2)CLR强制任何即将被卸载的APP域上的线程抛出一个ThreadAbortEx,如果未处理,CLR忽略之,线程死亡,进程继续执行.
      • 3)遍历加载器堆,ProxyObject设置为无效.调用其上方法
      • 4)GC.
      • 5)CLR恢复生育线程的运行.如果调用UnLoad的线程位于即将卸载的APP,CLR创建一个新线程来试图卸载APP,如果10秒超时后,后果不可知.
  • 宿主.
    • 1)IE:安装FrameWork,会同时安装一个MIME筛选器(MSCorIE.dll)挂接到IE,其处理”Application/octect-streame(x-msdownload)”MIME类型的下载内容.当检查到有一托管AM被下载时,会调用CorBindToRuntime来加载CLR.CLR控制,使得不同的WEB站点有各自的APP,不同的权限集,互补影响.
    • 2)ASP.NET:作为一个ISAPIASPNet_ISAPI.dll内实现.Client第一次请求时加载CLR.对同一Web App的请求仅会在第一次时创建一APP,之后使用同一个进行处理.另一个Web APP被请求时,CLR创建新的APP.Asp.Net可以在不关闭Web Server,修改代码,会自动卸载旧的正在运行的版本,后加载新版本.
    • 3)Sql Server(本身是非托管的C++代码写的):第一次请求一个托管代码写的存储过程时加载CLR.之后在各自验证过的APP域内运行.
  • 宿主控制.
    • 1)构建一个APPDomainManager派生类于一AM,将该AM装到GAC下以拥有Full_Trust权限.由于一个进程只能有一个该类型派生类,CLR与其关联:非宿主API/环境变量/注册表Key. 
    • 2)健壮:体面中断:资源清理被执行,不中断Catch/Finally块中的线程;粗鲁中断:资源不被清理,中断Catch/Finally块中的线程.但位于非托管区或临界执行区(进入同步锁并等待的线程,其访问的数据位同一APP域内多线程共享的)的线程无法中断.先体面后粗鲁中断APP域.
  • 程序集的加载
    • CLR不支持卸载单AM,而必须卸载含有该AMAPP.
    • 性能.
      • 1)编译时类型不安全(使用字符串),运行时可能找不到;
      • 2)运行速度慢(通过字符串扫描AM的元数据,不区分大小写);
      • 3)使用反射调用成员更慢(要将参数打包为[],解包到堆栈之前还要检查参数的;类型正确与否).
      • 所以,如果需动态发现和构建一类型:让该类型实现一编译时已知类型的接口,运行时构建该类型实例,并将其引用放于一个该接口变量中,之后即可调用方法.

 

posted @ 2014-06-14 11:36  robynhan  阅读(478)  评论(0编辑  收藏  举报