隔离应用程序的优点

操作系统和运行时环境通常会在应用程序间提供某种形式的隔离。例如,Windows 和 Unix 使用进程来隔离应用程序 。为确保在一个应用程序中运行的代码不会对其他不相关的应用程序产生不良影响,这种隔离是必需的。使用进程边界来隔离在同一台计算机上运行的应用程序。每一个应用程序被加载到单独的进程中,这样就将该应用程序与在同一台计算机上运行的其他应用程序相隔离。 隔离这些应用程序的原因在于内存地址是与进程相关的;在目标进程中,不能通过任何有意义的方式使用从一个进程传递到另一个进程的内存指针。此外,您不能在两个进程间进行直接调用。您必须使用代理/管道等手段,它提供一定程度的间接性。

隔离应用程序对于应用程序安全也是十分重要的。例如,您可以在单个浏览器进程中运行几个 Web 应用程序中的控件,同时使这些控件不能访问彼此的数据和资源。

应用程序域

应用程序域是.NET框架中非常重要的概念。 它为安全性、可靠性、版本控制以及卸载程序集提供了隔离边界。由运行时宿主 (HOST) 创建,运行时宿主负责在运行应用程序之前引导公共语言运行时。在开发普通的WinForm程序时,应用程序域的作用不是非常明确,但如果开发Asp.net,Nt Service, SOA等服务为主体的应用程序时,熟悉应用程序域是非常有必要的。

使用应用程序域隔离可能终止进程的任务。如果正在执行任务的 AppDomain 的状态变得不稳定,则可以卸载 AppDomain,但不会影响进程。 当进程必须不重新启动而长时间运行时,这一点很重要。还可使用应用程序域隔离不应共享数据的任务。

  • 如果程序集被加载到默认应用程序域中,则当进程运行时将无法从内存中卸载该程序集。但是,如果打开另一个应用程序域来加载和执行程序集,则卸载该应用程序域时也会同时卸载程序集。使用此技术最小化长时间运行的进程的工作集,这些进程偶尔会使用大型 DLL。
  • 在一个应用程序中出现的错误不会影响其他应用程序。因为类型安全的代码不会导致内存错误,所以使用应用程序域可以确保在一个域中运行的代码不会影响进程中的其他应用程序。
  • 能够在不停止整个进程的情况下停止单个应用程序。使用应用程序域使您可以卸载在单个应用程序中运行的代码。
  • 托管代码必须先通过一个验证过程,然后才能运行(除非管理员已授权跳过该验证)。此验证过程将验证以下内容:这些代码是否会尝试访问无效的内存地址?是否会尝试执行某些导致进程(该代码运行时所在的进程)无法正常进行的其他操作?通过此验证测试的代码将被认为是类型安全的。由于公共语言运行时能够验证代码是否为类型安全的代码,所以它可以提供与进程边界一样大的隔离级别,而其性能开销则要低得多。
  • 应用程序域提供了一个更安全、用途更广的处理单元,公共语言运行时可使用该单元提供应用程序之间的隔离。您可以在具有同等隔离级别(存在于单独的进程中)的单个进程中运行几个应用程序域,而不会造成进程间调用或进程间切换等方面的额外开销。在一个进程内运行多个应用程序的能力显著增强了服务器的可伸缩性。
  • 不能卸载单个程序集或类型。只能卸载整个域。
  • 在一个应用程序中运行的代码不能直接访问其他应用程序中的代码或资源。为了强制实施此隔离,公共语言运行时禁止在不同应用程序域中的对象之间进行直接调用。要在各域之间传递对象,可以复制这些对象,或通过代理访问这些对象。如果复制对象,那么对该对象的调用为本地调用。也就是说,调用方和被引用的对象位于同一应用程序域中。如果通过代理访问对象,那么对该对象的调用为远程调用。在此情况下,调用方和被引用的对象位于不同的应用程序域中。域间调用所采用的远程调用基础结构与两个进程间的调用或两台计算机间的调用的基础结构相同。因此,被引用的对象的元数据必须对于两个应用程序域均可用,以便用 JIT 正确编译该方法调用。如果调用域对被调用对象的元数据没有访问权,则编译可能失败,并引发类型为 System.IO.FileNotFound 的异常。
  • 代码行为的作用范围由它运行所在的应用程序决定。换言之,应用程序域将提供应用程序版本策略等配置设置、它所访问的任意远程程序集的位置,以及加载到该域中的程序集的位置信息。
  • 向代码授予的权限可以由代码运行所在的应用程序域来控制。
  • 多个应用程序域可以在一个进程中运行;但是,在应用程序域和线程之间没有一对一的关联。多个线程可以属于一个应用程序域,尽管给定的线程并不局限于一个应用程序域,但在任何给定时间,线程都在一个应用程序域中执行。

AppDomain

应用程序域(由 AppDomain 对象表示)为执行托管代码提供隔离、卸载和安全边界。 应用程序域 ( AppDomain ) 是从.NET 1.0开始就一直存在于System名字空间,它能够在应用程序进程内建立起独立的执行环境。其原始定义为:

[ComVisibleAttribute(true)]
[ClassInterfaceAttribute(ClassInterfaceType.None)]
public sealed class AppDomain : MarshalByRefObject,_AppDomain, IEvidenceFactory

此类从 MarshalByRefObject继承,实现了_AppDomain 和 IEvidenceFactory 接口。 MarshalByRefObject 允许在支持远程处理的应用程序中跨应用程序域边界访问对象。

使用 CreateDomain 方法创建应用程序域。 AppDomain 实例用于加载和执行程序集 ( Assembly)。 当不再使用 AppDomain 时,可以将它卸载。

AppDomain 类实现一组事件,这些事件使应用程序可以在加载程序集、要卸载应用程序域或引发未经处理的异常时进行响应。

在任何情况下都不应创建 AppDomain 对象的可远程控制的包装,即不要使用WCF技术将AppDomain对象丢给远程访问者。 因为,这样做可发布对该 AppDomain 的远程引用,将诸如 CreateInstance 方法向远程访问公开,并有效损坏该 AppDomain 的代码访问安全性。 连接到远程 AppDomain 的恶意客户端可以获得对 AppDomain 本身可访问的所有资源的访问权。 您不应为任何以下类型创建可远程控制的包装:扩展 MarshalByRefObject 的类型和实现恶意客户端可用来绕过安全系统的方法的类型。

应用程序域和程序集之间的关系

在可以执行程序集中所包含的代码之前,必须将程序集加载到应用程序域中。在运行反射类型时,加载被引用的程序集是必须的。运行普通的应用程序会导致将几个程序集加载到一个应用程序域中。

程序集的加载方式决定其实时 (JIT) 编译代码是否可以在进程中由多个应用程序域共享,以及该程序集是否可以从进程中卸载。

  • 如果程序集是以非特定于域的形式进行加载,则共享相同安全授权集的所有应用程序域都可以共享相同的 JIT 编译代码,从而减少应用程序所需的内存。但是,程序集则永远不能从进程中卸载。
  • 如果程序集不是以非特定于域的形式进行加载,则它必须在加载的每个应用程序域中都是 JIT 编译的。但是,通过卸载程序集加载的所有应用程序域,可以从进程中卸载程序集。

运行时宿主决定在将运行时加载到进程中时是否以非特定于域的形式加载程序集。对于托管应用程序,将 LoaderOptimizationAttribute 特性应用于进程的入口点方法,并从关联的 LoaderOptimization 枚举指定一个值。 对于承载公共语言运行时的非托管应用程序,当您调用 CorBindToRuntimeEx 函数 方法时,指定适当的标志。

有三个选项用于加载非特定于域的程序集:

  • SingleDomain 不以非特定于域的形式加载任何程序集(Mscorlib 除外,它始终以非特定于域的形式加载)。 此设置称作单域,因为它通常用在宿主只运行进程中的单个应用程序时。
  • MultiDomain 以非特定于域的形式加载所有程序集。 此设置用于以下情况:进程中有多个应用程序域,所有这些应用程序域均运行相同的代码。
  • MultiDomainHost 以非特定于域的形式加载强名称程序集(如果它们以及它们的所有依赖项都已在全局程序集缓存中安装)。 其他程序集都将针对它们加载的每个应用程序域分别进行加载和 JIT 编译,从而可以从进程中卸载。如果您在同一进程中运行多个应用程序,或者如果您有混合的程序集,其中包括许多应用程序域共享的程序集和需要从进程中卸载的程序集,则可以使用此设置。

以下程序集不能共享 JIT 编译代码:使用 Assembly 类的 LoadFrom 方法加载到“加载源”上下文中的程序集,或者使用 Load 方法的重载(指定字节数组)从图像加载的程序集。

使用 Ngen.exe(本机映像生成器) 编译为本机代码的程序集如果在第一次加载到进程中时是以非特定于域的形式加载的,则可以在不同应用程序域之间共享这些程序集。

包含应用程序入口点的程序集的 JIT 编译代码只有在其所有依赖项都可以被共享的情况下,才可以被共享。

非特定于域的程序集可以进行多次 JIT 编译。例如,如果两个应用程序域的安全授权集不同,则它们不能共享相同的 JIT 编译代码。但是,JIT 编译程序集的每个副本都可以与其他具有相同授权集的应用程序域共享。

当您决定是否以非特定于域的形式加载程序集时,必须在减少内存占用和降低其他性能因素之间加以权衡。

  • 对于非特定于域的程序集,对静态数据和方法的访问较慢的原因在于需要隔离程序集。访问该程序集的每一应用程序域都必须具有静态数据的单独副本,以避免跨域边界引用静态字段中的对象。因此,运行时包含附加的逻辑,用以将调用方引导到静态数据或静态方法的适当副本。这一额外的逻辑将降低调用速度。
  • 当以非特定于域的形式加载程序集时,必须找到并加载该程序集的所有依赖项,因为如果一个依赖项不能以非特定于域的形式加载,则会妨碍以非特定于域的形式加载程序集。

应用程序域和线程之间的关系

应用程序域为安全性、版本控制、可靠性和托管代码的卸载形成隔离边界。线程是公共语言运行时用来执行代码的操作系统构造。在运行时,所有托管代码均加载到一个应用程序域中,由托管线程来运行。

应用程序域和线程之间不具有一对一的相关性。在任意给定时间,在单个应用程序域中可以执行几个线程,而且特定线程并不局限在单个应用程序域内。也就是说,线程可以自由跨越应用程序域边界;不为每个应用程序域创建新线程。

在任意给定时间,每一线程都在一个应用程序域中执行。在任何给定的应用程序域内可能有零个、一个或多个线程正在执行。运行时会跟踪在哪些应用程序域中有哪些线程正在运行。通过调用 GetDomain 方法,您可以随时确定线程执行所在的域。

可以向线程附加 CultureInfo 对象。但是,为了防止恶意代码进入其他应用程序域, CultureInfo 对象在其线程跨越应用程序域边界时自动被设置为只读。

如果对 CultureInfo 对象进行了自定义(例如使用自定义 Calendar),则会在线程尝试跨越应用程序域边界时引发 InvalidOperationException。

对应用程序域进行编程

应用程序域通常由运行时宿主以编程的方式来创建和操作。但是,有时应用程序还可能要和应用程序域结合起来使用。例如,应用程序可能将应用程序组件加载到域中以便能够在不停止整个应用程序的情况下卸载域(以及该组件)。

AppDomain 类是应用程序域的编程接口。此类包括各种方法,这些方法可以创建和卸载域、创建域中各类型的实例以及注册各种通知(如应用程序域卸载)。下表列出了常用的 AppDomain 方法。

CreateDomain 创建新的应用程序域。建议使用此方法指定 AppDomainSetup 对象的重载形式。 这是设置新域的各个属性的首选方式,这些属性包括应用程序基(即该应用程序的根目录)、域的配置文件的位置、以及公共语言运行时用于将程序集加载到域中的搜索路径等。

ExecuteAssemblyExecuteAssemblyByName  执行应用程序域中的程序集。这是一个实例方法,因此它可用来执行另一个应用程序域(您拥有对该域的引用)中的代码。

CreateInstanceAndUnwrap 在应用程序域中创建指定类型的实例,并返回一个代理。使用此方法以避免将包含创建的类型的程序集加载到调用程序集中。

Unload 执行域的正常关闭。只有应用程序域中正在运行的所有线程都已停止或域中不再有运行的线程之后,才卸载该应用程序域。 应用程序域可以在不停止整个进程的情况下卸载。宿主可以利用这一特点来卸载不再需要的代码,从而减少内存占用并增加其应用程序的可缩放性。

System. AppDomain 类包含一个名为 Unload 的静态方法,宿主可以使用该方法卸载特定的应用程序域。 AppDomain. Unload 执行的是正常关机,只要存在任何活动线程,它就不会卸载应用程序域。 如果不关闭整个进程,就无法卸载默认应用程序域中加载的程序集,或以非特定于应用程序域的方式加载的程序集。

公共语言运行时不支持全局方法序列化,因此不能使用委托来执行其他应用程序域中的全局方法。

公共语言运行时承载接口规范中介绍的非托管接口也提供对应用程序域的访问。运行时宿主可以使用非托管代码的接口在进程内创建应用程序域和获取对这些应用程序域的访问。

运行时宿主

公共语言运行时已经过专门设计,支持各种类型的应用程序,包括从 Web 服务器应用程序到具有传统的丰富 Windows 用户界面的应用程序在内的所有应用程序。每种应用程序都需要一个运行时宿主来启动它。运行时宿主将该运行时加载到进程中,在该进程内创建应用程序域,并且将用户代码加载到该应用程序域中。

.NET Framework 附带有多种不同的运行时宿主,包括下表中列出的宿主。

ASP.NET

将运行时加载到要处理 Web 请求的进程中。ASP.NET 还为将在 Web 服务器上运行的每个 Web 应用程序创建一个应用程序域。

Microsoft Internet Explorer

创建要在其中运行托管控件的应用程序域。.NET Framework 支持下载和执行基于浏览器的控件。运行时通过 MIME 筛选器与 Microsoft Internet Explorer 的扩展性机制相连接,以创建要在其中运行托管控件的应用程序域。默认情况下,将为每个网站创建一个应用程序域。

shell 可执行文件

每次从 shell 启动可执行文件时,都要调用运行时承载代码来将控制权转给该运行时。

Microsoft 提供了一组 API,可供开发人员开发自己的运行时宿主。

转载于:https://www.cnblogs.com/begincsdn/archive/2012/07/18/2596741.html

.NET 漫淡(一) --- 需要充分认识的应用程序域-AppDomain相关推荐

  1. 雷军的100亿计划:不服就干,生死看淡

    图片来自小米官网 整理 | 琥珀 出品 | AI 科技大本营 1 月 10 日,红米品牌正式独立. 11 日,雷军在小米年会上宣布,2019 年,小米将正式启动"手机+AIoT"双 ...

  2. 某程序员leader吐槽自己的工作就是合并周报!撕逼扯淡!跪舔领导!月薪五万却非常焦虑!...

    互联网大厂的leader,听起来很牛的样子,他们的工作是不是也很牛呢? 一个leader发帖抱怨说自己虽然月薪五万,却时常陷入焦虑中,觉得自己工作没有价值,再这样下去就废了!让我们看看他都说了些什么? ...

  3. apache2.4.9 开启path_info访问_浅淡flask在win下用Apache24及mod_wsgi部署的那些坑

    浅淡flask在win下用Apache24及mod_wsgi部署的那些坑 安装部署就不指描述了,毕竟网上多得很,就说说一些坑吧. 1.中文路径问题,正常情况,Apache里配置文件用中文路径是会出错的 ...

  4. python语言中文社区-扯个淡:用Python实现中文编程

    既然是扯淡,就不要当真.所谓"中文编程"就是用中文写写代码,不管你看着累不累,我写着就得累死- "中文编程"由来已久,不知道你听说过"易语言" ...

  5. CSAPP第五章就在“扯淡”!

    "你的时间有限,所以不要为别人而活.不要被教条所限,不要活在别人的观念里.不要让别人的意见左右自己内心的声音.最重要的是,勇敢的去追随自己的心灵和直觉,只有自己的心灵和直觉才知道你自己的真实 ...

  6. 人生百味,浓缩到最后就是一个淡字

    1.人生百味.浓缩到最后就是一个淡字. 人缘,不是有多少人认识你,而是有多少人愿意帮助你.人脉,不是你利用过多少人.而是你帮助过多少人:人气.不是有多少人在你面前吹捧你,而是有多少人在你背后称赞你. ...

  7. 友商逼急 雷急跳墙:生死看淡 不服就干

    友商逼急    雷急跳墙:生死看淡 不服就干 短短一个小时的红米Note7手机产品发布会,雷军怼了友商8次:甚至在媒体群访环节,雷军也抑制不住愤怒之情,提到友商面色铁青,以至于有人说,这次发布会的雷军 ...

  8. 浅淡Webservice、WSDL三种服务访问的方式(附案例)

    Webservice Webservice是使应用程序以与平台和编程语言无关的方式进行相互通信技术. eg:站点提供访问的数据接口:新浪微博.淘宝. 官方解释:它是一种构建应用程序的普遍模型,可以在任 ...

  9. 淡季不淡!速卖通户外运动产品好做吗?来看看法国这些爆款!

    淡季不淡,帶你看看速卖通主要市场"法国"秋天玩什么运动! 进入初秋,很多运动行业商家都会面临销售淡季.暑期刚法国流行什么运动,成了困扰商家的一个大问题.今天让热法国流行什么运动,成 ...

  10. 将Windows 8.1 系统窗口背景设置成淡绿色?

    1.右键点击开始→运行. 2.在运行中输入: regedit 按回车键之后,打开注册表编辑器. 3.依次定位到:HKEY_CURRENT_USER\Control Panel\Colors. 4.然后 ...

最新文章

  1. ServiceModel 元数据实用工具 (Svcutil.exe)
  2. linux 文本处理 awk 几个特殊的内置变量
  3. linux tomcat守护_linux下非root用户运行tomcat
  4. 杂项-EMS:CRM
  5. python进阶21之actor
  6. android列表项点击事件,Android 开发 tips(2):监听 Listview 列表项点击事件
  7. 中金财富:如何获取不“平均”的收益?
  8. 直流电机PID控制源码c语言,51单片机PID+PWM直流电机转速闭环控制源码(12864液晶显示)...
  9. 如果报华为网络工程师中级培训班一般学费多少?
  10. 手握百万恶意IP,阿里云要跟黑客拼了 | 云栖大会
  11. 主页 被 2345 篡改怎么办
  12. 希望我能帮助你:关于软件开发的建议
  13. linux下登录不上oracle,Oracle特定用户登录失败案例 ORA-20001
  14. 国家级精品课程 电子资源 网址
  15. 数字信号处理FFT快速傅立叶变换MATLAB实现——实例
  16. 2017物联网蓬勃发展,看各领域巨头如何抢先机占山头
  17. “华为杯”研究生数学建模竞赛2020年-【华为杯】B题:降低汽油精制过程中的辛烷值损失模型(附获奖论文)
  18. iOS 16老机型落幕:iPhone 7、iPhone 6S和iPhoneSE 2016无法更新
  19. 店群怎么玩?2020最新玩法介绍 胖哥给大家分享干货
  20. 解决git clone时报SSL错误

热门文章

  1. 数据仓库模型与缓慢变化维度技术深度剖析-DW商业环境实战
  2. 正则表达式校验特殊格式
  3. PHPExcel导出Excel方法总结——ThinkPHP5
  4. 《Python编程实战:运用设计模式、并发和程序库创建高质量程序》—— 2.7 代理模式...
  5. 点击空白处隐藏指定dom元素(纯javascript方法)
  6. Silverlight 数据绑定 (1):怎样实现数据绑定 Silverlight 数据绑定 (2):Source to Target...
  7. mysql force Index 强制索引[转]
  8. list.h双循环链表的实现,拷贝自Linux内核(2.6.20.1)
  9. RBM,DBM和DBN之间有什么区别?
  10. Socket Programming