|
我们同样可以借助上面定义的AppDomainContext来证实这一点。在这之前我需要解释一点:程序集的加载包含对定义在程序集中类型体系的加载,我们可以通过类型对象的加锁情形来推断程序集的加载方式。为此我在上面创建的解决计划中增加了一个类库名目Lib,ConsoleApp引用Lib项目,并在Lib中定义了一个空的Foo类型。 三、字符串的驻留为了便于演示,我写一个如下一个AppDomainContext,表示某个AppDomain对应的执行上下文。AppDomainContext拥有一个只读的类型为的属性,该属性通过结构函数执行,终极在静态方法NewContext被创建。我们调用Invoke方法让指定的方法对应的应用程序域中执行。 当托管应用被启动后,在履行第一句代码之前,CLR会先后为我们创建三个应用程序域:系统程序域(System Domain)、共享程序域(Shared Domain)和默认程序域(Default Domain),它们分离具备不同的作用。 又一个关于加锁的留神:谨严地对Type对象进行加锁。 二、系统程序域、共享程序域和默认程序域而后我再一个掌握台应用中的Main方法中,编写了如下简略的代码。通过AppDomainContext在一个的应用程序域(Foo)中锁定一个值为“Hello World!”的字符串,并在另一个应用程序域(Bar)中确认同值得字符串是否已经被锁定。结果表现在应用程序域Bar中指定的字符串已经被锁定,太阳城娱乐城,从而证明了应用程序域Foo和Bar中两个值为“Hello World,博彩网!”的字符串对象实际上是同一个。 然后我们修正之前的程序,将对字符串加锁替代在对Foo类型(typeof(Foo))加锁。从输出结果我们可以看出,在Bar程序域中使用的Foo类型并不被锁住,从而证明两个程序域(Foo和Bar)使用的同一个类型并不是Type对象,因为对应的程序集是以独占的方式加载的。 固然我们说CLR在启动托管应用的时候,以中立域的方式加载msCorLib.dll这个程序集,六合彩修改,但是这不是程序集默认采用的加载方式。在默认的情况下,程序集被加载到当前的程序域中,供该程序集独占使用。我个人将这两种不同的程序集加载方式称为:独有加载(Exclusive Loading )和共享加载(Shared Loading)。如右图所示:如果某个类型被定义在程序集中Foo.Dll,当AppDomain1和AppDomain2需要使用该类型的时候,它们会分辨以独占的方式加载程序集Foo.Dll。但是,如果它们使用一些基元类型,比如System.Object、System.Int32、System.DateTime等,则不会加载定义它们的msCorLib.dll程序集,而是直接使用已经被以中立域方式加载到共享程序域中的msCorLib.dll。 输出结果: 上面的文字描述实际上流露一些主要的信息,其中一个就是字符串的驻留(String Interning)。关于字符串的驻留,我想大家都不生疏,所以在这里我就不作反复的先容了。在这里,我只想讨论一个问题:字符串的驻留是基于全部进程的,而不是仅仅基于某个应用程序域。 何谓程序集(Assembly)?它是一个托管应用的基本的部署单元。一个程序集是自描述的(通过元数据)、能够实行版本策略和安排策略。我偏向于这样的方式来定义程序集:“Assembly is a reusable, versionable, and self-describing building block of a CLR application.”从结构组成来看,一个程序集主要由三个部署组成:IL指令、元数据和资源。程序集的构造组成如下图所示。 那么什么又是应用程序域呢?从功效上讲,通过应用程序域实现的隔离机制为托管代码的执行供给了一个保险的边界。从与程序集的关联来讲,我们可以将应用程序域看成是加载程序集的容器。只有相干的程序集被CLR加载到相应的应用程序域中,才谈得上代码的执行。 那么,我们是否能够通过一些比拟直观的方法来验证这一点。但是,我们不能直接编写程序来比较两个应用程序域中字符串是否是雷同的引用,然而我们有一些间接的机制。我个人爱好采取的方式是:加锁。我们在运行于不同的应用程序域的代码中对两个字符串变量进行加锁,如果程序运行的结果和对相同的对象加锁一样,那么就可以证明被枷锁的两个对象实际上是同一个对象。 半年之前,太阳城娱乐城,PM让我在部分内部进行一次对于“内存泄漏”的专题分享,我为此筹备了一份PPT。今天无意中将其翻出来,感到里面提到的关于CLR下关于内存治理局部的内存还有点意思。为此,今天依照PPT的内容写了一篇文章。本篇文章不会在探讨那些咱们熟习的话题,比方“值类型援用类型存在怎么的差别?”、“垃圾回收分为多少个步骤?”、“Finalizer和Dispose有何不同”、等等,而是讨论一些不同的内容。整篇文章分高低两篇,上篇重要念叨的是“程序集(Assembly)跟利用程序域(AppDomain)”。兴许有的处所说的不是很准确,盼望读者不吝赐教。 基于应用程序域的隔离,归根结底是内存的隔离。一个基础的反应就是:在一个运用程序域中创立的对象,不能直接在另一个应用程序域中应用。这旁边须要有一个根本的跨应用程序域传递的机制,我们将这种机制称之为“封送(Marshaling)”。详细来讲,又具有两种不同的封送方式:按值封送(MBV:Marshaling By Value )和按引用封送(MBR:Marshaling By Reference)。MBV主要采用序列化的方式,而MBR最典范的就是.ENT Remoting。 我想到这里有人会问一个问题:“我们自定义的程序集可以像msCorLib.dll一样以中立域的方式共享加载吗?”。对把持台应用,你只要要在Main办法上应用特征,并指定为MultiDomain即可。好比,仍是采用对Foo类型Foo类型(typeof(Foo))对象加锁,这次我们在Main方法上应用了这样的特性:[LoaderOptimization(LoaderOptimization.MultiDomain)]。输出的结果就与对Int32类型对象加锁一样。 上面的介绍同时说明一个问题:千万不要对一个字符串对象加锁。 输出结果: 一、程序集与应用程序域 输出结果: 输出结果: 四、程序集加载的方式但是,假如我们将加锁和锁定测验的typeof(Foo)调换成typeof(int),结果就完整不一样了。不同的成果阐明了msCorLib.dll采用了不同于上面的程序集加载方式,以中破域方式的加载方式决议在任何应用程序域中使用的类型都是统一个Type对象。 从上面的描写我们晓得,字符串对象和普通的引用类型对象具有很大的不同:字符串对象直接被保留到系统程序域中,而个别的引用类型对象我们都是最终保存在GC堆中。从某种意思上讲,在字符串驻留机制下,字符串也是以“中立域”的方式被加载的,被驻留的字符串可能被同一个过程下所有应用程序域所共享。 我们接着在定义一个帮助类ObjectLock便利进行加锁,以及确认对象是否被所住。ObjectLock比如继续自MarshalByRefObject,由于我们需要该对象以MBR的方式进行传递。在Lock方法中对指定的对象进行加锁,并指定加锁的时光。在CheckLock中通过期间距离断定指定的对象是否已经被锁住,相应的结果会在节制台中被输出,股票开户。为了让大家可以断定相应的操作是在哪个应用程序域中执行的,在桎梏和检讨锁定的时候将应用程序域的名称(AppDomain.FriendlyName属性)打印出来。 五、我们本人的程序集也可以采用中立域的方式加载吗?
(责任编辑:admin) |
