一个很好的使用AppDomain的例子

50
我一直被问到关于AppDomains的问题,在面试中,我知道基本概念

  • 它们是应用程序内部的隔离级别(使它们不同于应用程序)
  • 它们可以拥有线程(使它们不同于线程)
  • 一个AppDomain中的异常不会影响另一个AppDomain
  • AppDomains不能访问彼此的内存
  • 每个AppDomain可以具有不同的安全性

我仍然不明白它们为什么必要。我正在寻找一个合理的具体情况,您何时会使用它。

答案:

  • 不受信任的代码
    • 核心应用程序受保护
      不受信任/第三方插件通过在单独的AppDomain中进行隔离并带有安全限制来防止损坏共享内存或未经授权访问注册表或硬盘,从而保护应用程序或服务器,例如ASP.NET和SQL Server托管组件代码
  • 受信任的代码
    • 稳定性
      将应用程序分成安全、独立的功能和特性
    • 架构灵活性
      自由运行多个应用程序在单个CLR实例中或者每个程序在各自的实例中。

还有其他需要补充的吗?


作为进程和线程之间的中间抽象层,其优缺点自然而然地出现。 - John Z. Li
7个回答

50

16

正如您在问题中提到的,AppDomains 的另一个好处是加载到其中的代码可以以不同的安全权限运行。例如,我编写了一个应用程序来动态加载 DLL。我是一名教师,这些 DLL 是我要加载的学生 DLL。我不想让一些不满意的学生清除我的硬盘或破坏我的注册表,因此我将他们 DLL 中的代码加载到一个不具有文件 IO 权限、注册表编辑权限甚至不具有显示新窗口权限(它实际上只具有执行权限)的单独 AppDomain 中。


8
我认为创建应用程序域的主要动机是CLR设计者想要一种隔离托管代码的方法,而不会产生多个Windows进程的性能开销。如果CLR最初是在UNIX上实现的(在那里创建多个进程的成本显着降低),则可能永远不会发明应用程序域。
此外,尽管在第三方应用程序中使用托管插件体系结构绝对是应用程序域的良好用途,但它们存在的更大原因是为了众所周知的主机,如SQL Server 2005和ASP.NET。例如,ASP.NET托管提供程序可以提供支持来自多个客户的多个站点的共享托管解决方案,所有这些站点都在单个Windows进程下运行。

线程可以跨越应用程序域边界流动。这可能是应用程序域和进程之间最重要的区别。虽然*NIX进程比其Windows对应物更轻量级,但是应用程序域之间的通信比IPC更方便,无论平台如何。 - John Z. Li

4
如果您创建了一个允许第三方插件的应用程序,您可以将这些插件加载到单独的AppDomain中,以便您的主应用程序不受未知代码的影响。
ASP.NET还为单个工作进程中的每个Web应用程序使用单独的AppDomain。

4

应用程序域对于应用程序的稳定性非常有帮助。

通过让应用程序由一个中央进程组成,然后在单独的应用程序域中生成“功能”,您可以防止全局崩溃,如果其中一个出现问题。


4
据我了解,AppDomain的设计旨在允许托管实体(操作系统、数据库、服务器等)在单个CLR实例中运行多个应用程序,或者每个程序在其自己的实例中运行。因此,这是主机而不是应用程序开发人员的问题。
与Java相比,这种设计更加有利,因为Java总是为每个应用程序提供1个JVM,这经常导致许多JVM实例并行运行,资源重复。

3
我看到创建独立应用程序域的主要用途有两到三个:
1)使用类似进程隔离的方式,资源使用率低,开销小。例如,ASP.NET就是这样做的——它在单独的应用程序域中托管每个网站。如果在单个应用程序域中使用不同的线程,则不同网站的代码可能会相互干扰。如果将不同的网站托管在不同的进程中,则会使用大量资源,并且与进程内通信相比,进程间通信相对困难。
2)在具有特定安全权限的单独应用程序域中执行不受信任的代码(实际上与第一点原因有关)。正如其他人已经说过的那样,您可以将第三方插件或不受信任的DLL加载到单独的应用程序域中。
3)能够卸载程序集以减少不必要的内存使用。不幸的是,没有办法从应用程序域中卸载程序集。因此,如果您将某个大型程序集加载到主应用程序域中,则在不再需要该程序集之后释放相应的内存的唯一方法是关闭应用程序。在单独的应用程序域中加载程序集并在不再需要时卸载该应用程序域是解决此问题的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接