参考链接:https://www.cnblogs.com/asminfo/p/3999412.html
为了保证代码的键壮性CLR希望不同服务功能的代码之间相互隔离,这种隔离可以通过创建多个进程来实现,但操作系统中创建进程是即耗时又耗费资源的一件事,所以在CLR中引入了AppDomain的概念,AppDomain主要是用来实现同一进程中的各AppDomain之间的隔离,AppDomain可以用以下特征来描述它的全貌:
-
AppDomain概念并不存在于操作系统,而只存在于.net中并且AppDomain不可脱离进程单独存在,它是属于某一CLR或寄宿着CLR的进程的。
-
一个进程中可以有多个AppDomain,并且每个之间相互隔离(只保证安全代码的隔离,不安全代码并不能保证),此可以理解为AppDomain是.net程序中的"进程",在一个AppDomain中创建的对象只属于本AppDomain,多个AppDomain之间的对象不能相互访问,除非遵循CLR的一些规则。
-
.net程序启动时在进程中创建一个默认的AppDomain,入口代码将运行于此AppDomain,默认应用程序域只有在进程终止时才会被销毁,如果主动的调用Unload去卸载默认应用程序域,会抛出一个CannotUnloadAppDomainException。
-
每个AppDomain都单独的加载程序集,这意味着在A应用程序域中加载了的程序集,并不一定在B应用程序域中也被加载了。每个APPDomain有单独的Loader堆,互相不影响,每个Loader堆都记录了自AppDomain建立以后所访问过的类型,Loader堆中的每个类型对象都有一个方法表,这些方法表指向已经被JIT编译过的本地代码(前提是这些方法是已经被至少执行过一次的)。因为AppDomain是相互隔离的所以相同的一个类型中的方法,在A应用程序域中是被JIT编译过的,但不一定在B应用程序域中也是被JIT编辑过的,方法是否被JIT编辑过取决于些方法是否在本AppDomain被调用过。
-
当AppDomain被卸载时,此AppDomain中的程序集会被卸载,因为每个APPDomain加载的程序集都是独立的所以一个应用程序域被卸载并不会影响其它AppDomain中加载的程序集,另外本AppDomain的loader堆也会被回收,每个程序域的loader堆是独立的所以也不会影响到其它程序域的Loader堆,因为loader堆是独立的(静态字段是存在于类型对象上的),所以一个类型中的静态字段在不同应用程序域中也是不同的存在,所以静态字段也是不被影响的,唯一受影响的是线程,因为线程可以跨越应用程序域访问不同的应用程序域上的代码,后面我们会介绍当卸载一个应用程序域时如果对线程做处理。
-
有一种程序集可以被多个AppDomain使用,这种程序集叫做"AppDomain中立"的程序集,比如MSCorLib.dll,该程序集包含了System.Object,System.Int32以及其它的与.net framework密不可分的类型,这个程序集在CLR初始化时会自动加载,JIT会为这些程序集创建一个特殊的Loader堆,并且程序集中的方法被编译成的本地代码可被所有AppDomain共享,这种程序集不可被卸载只有当进程结束时这种程序集才会被卸载。
AppDomain的创建与销毁
-
System.Threading.Thread .GetDomain()得到当前线程所在的应用程序域,或通过AppDomainr的一个静态只读属性:AppDomain.CurrentDomain
-
创建AppDomain使用AppDomain的静态方法CreateDomain这个方法有多个重载版本,最简单的AppDomain.CreateDomain("domain 1");参数传入的是AppDomain的友好名称,调用这个版本的方法,新建的AppDomain会使用当前AppDomain的权限集和配置设置。其它版本可自动查阅文档。