zoukankan      html  css  js  c++  java
  • 第二十二章 CLR寄宿和AppDomain

    1. 概念解析

    CLR Hosting(CLR 宿主):初始启动.Net Application时,Windows进程的执行和初始化跟传统的Win32程序是一样的,执行的还是非托管代码,只不过由于PE文件中引入了CLR Header,OS进程加载了mscoree.dll,从而启动了CLR,CLR本身不是一个可执行程序,它需要一个进程来装载并启动它,从而接管进程并创建自身的程序运行上下文,这个过程可称之为CLR Hosting。从本质上来讲,CLR是一个COM服务器,它自身封装了一系列称之为CLR Hosting APIs的接口,以便于CLR寄宿于非托管程序,从而在非托管环境上下文中执行托管程序。比如SQL Server2005和ASP.NET都运用了此种技术使CLR寄宿于其运行环境。托管代码是如何在目标进程内执行的

    2. 托管程序与非托管程序的区别

    参考:

    对于托管的和非托管的程序集编译器都会把程序集编译成以.exe或.dll等为扩展名的文件,可见Windows加载器并没有区分是托管还是非托管的程序集.

    对于托管还是非托管程序集,他们在编译器执行编译时都会编译成一个特殊的文件格式,即PE文件(可移植可执行文件格式),操作系统加载器通过加载这样的PE文件来执行程序集的。可以这么说吧,无论是托管程序还是非托管程序他们实际上都是编译成这样的PE文件(只是有部分内容不一样而已).

    然后这个PE文件会指示如何执行托管程序集和非托管程序集,加载器首先会查找到PE头中的AddressOfEntryPoint域,这个域指示PE文件的入口点位置,在.NET程序集中是指向.text段中的CLR头--〉包含一个结构IMAGE_COR20_HEADER—>包含许多信息如托管代码应用程序的入口点,目标CLR的主版本号和从版本号,以及程序集的强名称签名等--〉Windows加载器根据这个数据结构决定加载哪个版本的CLR以及一些基本的程序集信息。在.text段中还包含了程序集的元数据表,MSIL以及非托管启动存根代码,而非托管启动存根代码包好了由Windows加载器执行役启动PE文件执行的代码

    (1)非托管程序的执行过程
    在非托管程序中,可执行里面保存的是机器代码,CPU可以直接加载并执行,当系统加载了可执行程序后,系统就将可执行文件的段基址加上偏移地址形成实际的物理地址,并直接加载到内存中运行。

    (2)托管程序的执行过程
    托管程序的可执行文件中,包含的是中间语言以及元数据,当然不能直接运行,必须启动CLR,由CLR对中间语言进行即时编译成机器代码,并加载到内存里面执行(具体过程:程序在进入入口函数前会提前跳转到MSCoree.dll中,调用它的代码来启动CLR并完成一些初始化工作)。当然,IL中的方法并不是每次被调用都会被编译一次,而是它只有在第一次调用时才进行编译,即时编译器会将方法名称以及对应的入口地址存放在映射表中,当下次调用该方法时,会直接从映射表里去而不是再编译一次。

    3. AppDomain

    AppDomain: 是一个CLR的功能,Windows对AppDomain一无所知.线程和AppDomain没有一对一的关系.

    Thread.GetDomain查询线程正在执行那个AppDomain. System.AppDomain.CurrentDomain获取同样的信息.

    CLR在我们的任何代码运行之前就创建了默认的 AppDomain,并且用可执行文件的文件名作为默认的AppDomain的友好名称.

    跨越AppDomain边界访问对象

    System.Runtime.Remoting.RemotingServices.IsTransparentProxy 返回一个布尔值,该值指示给定的对象是透明代理还是实际对象

    按引用封送: MarshalByRefObject 抽象类,允许在支持远程处理的应用程序中跨应用程序域边界访问对象.实现这个类的类型可以跨域按照引用封送.

    按值封送:如果一个对象没有实现MarshalByRefObject ,但是具有Serializabled属性,就可以序列化按值封送.

    使用不可封送的类型跨域访问,会抛出异常.

    监视AppDomain

    使用AppDomain.MonitoringIsEnabled=true获取或设置一个值,该值指示是否对当前进程启用应用程序域的 CPU 和内存监视。 一旦对进程启用了监视,则无法将其禁用。

    AppDomain FirstChanceException异常通知

    event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> FirstChanceException 当托管代码抛出异常时发生,在运行时在调用堆栈中搜索应用程序域中的异常处理程序之前.不能处理异常,也不能吞噬异常,只能接收一个通知.可以用来执行日志记录功能.

    Thread.GetDomain().FirstChanceException += Program_FirstChanceException;
            try {
                throw new Exception() { };

            } catch (Exception) {

            }

    private static void Program_FirstChanceException(object sender, FirstChanceExceptionEventArgs args)
        {这里可以收到通知

        }

  • 相关阅读:
    浪潮之巅阅读笔记
    人月神话阅读笔记3
    学习报告
    人月神话阅读笔记2
    学习报告
    第十一周学习总结
    软件杯项目——手写体识别
    第十周学习进度
    第九周学习进度
    《软件架构师的12项修炼》阅读笔记
  • 原文地址:https://www.cnblogs.com/zhangliming/p/3492174.html
Copyright © 2011-2022 走看看