如何证明Application Domain的隔离性

简介:

Application Domain可以看作是一个Assembly的逻辑容器。在程序执行过程中,如果遇到需要的Type并没有定义在已经加载的Assemblies中,CLR会把相应的Assembly加载的该Application Domain中。每个Application Domain都有一个属于自己的加载器堆(Loader Heap),用于维护从Application Domain创建以后所用到的所有的Type,以及这些Type对应的方法表——维护这样一个Mapping:定义在Type中的所有方法和经过JIT编译后x86代码(只考虑32bit处理器)。

Application Domain之间是相互隔离,互不干扰。在一个Application Domain创建的对象不能被另一个Application Domain直接调用,反映在内存分配上面——就是各个Application Domain使用各个独立的内存地址空间。一个对象根据他所对应的类型(如System.MarshalByRefObject通过传递引用的方式)或者属性(比如对于定义了System. SerializableAttribute的Type采用传递值得方式)以两种不同的方式在Application Domain之间传递——By Reference 和By Value。

这些都是地球人都知道的.NET的基本原理,但是相信很多人没有尝试过通过Coding的方式证明这种机制。

那么现在我们就先来看看我们的Sample: 


下面是运行结果的Screen Shot。


接下来我们来分析这段代码。

1. 我们首先定义个3个不同的Type,他们都一个相同的方法——GetAppDomain()用于获取执行该方法的真正的Application Domain。

  • GeneralType:一般的Type, 没有什么特别。
  • MarshalByValueType:定义了一个System. SerializableAttribute(你也可以通过使它实现System.Runtime.Serialization.ISerializable Interface来模拟这个Sample),它将以By Value的方式在不同的Application Domain之间传递。
  • MarshalByRefType:继承自System. MarshalByRefObject。该类型的对象它将以By Reference的方式在不同的Application Domain之间传递。

public  class GeneralType
    {
        AppDomain GetAppDomain()
        {
             return AppDomain.CurrentDomain;
        }
    }

    [Serializable]
     public  class MarshalByValueType
    {
         public AppDomain GetAppDomain()
        {
             return AppDomain.CurrentDomain;
        }
    }

     public  class MarshalByRefType : MarshalByRefObject
    {
         public AppDomain GetAppDomain()
        {
             return AppDomain.CurrentDomain;
        }
 }

2. 在Main()中我们首先创建一个新的Application Domain,并为他指定一个Friendly Name——newAppDomain。

AppDomain appDomain = AppDomain.CreateDomain("newAppDomain");

3. 接着我们分别在这个新建的Appliation Domain中创建我们在1中定义的3个类型的对象——generalObject,marshalByValueObject,marshalByRefObject,并试着把它传递到当前的Application Domain——Default Application Domain。从运行的结果我们可以看出,当我们传递generalObject的时候,一个Exception被抛出,从Error Message可以开出原因——“Type 'Artech.AppDomainIsolation.GeneralType' in assembly 'Artech.AppDomainIsolation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.”从而我们可以看出,一般的Type是不能在不同的Application之间传递的。

try
            {
                GeneralType generalObject = (GeneralType)appDomain.CreateInstanceAndUnwrap(assemblyName, "Artech.AppDomainIsolation.GeneralType");
            }
             catch (Exception ex)
            {
                Console.WriteLine("Fail to pass a general type instance created in another application domain to default appliction domain,beacuse \"{0}\"", ex.Message);
            }

            MarshalByValueType marshalByValueObject = (MarshalByValueType)appDomain.CreateInstanceAndUnwrap(assemblyName, "Artech.AppDomainIsolation.MarshalByValueType");
            MarshalByRefType marshalByRefObject = (MarshalByRefType)appDomain.CreateInstanceAndUnwrap(assemblyName, "Artech.AppDomainIsolation.MarshalByRefType");

4. 通过3,证明了标记的System. SerializableAttribute属性和继承自System. MarshalByRefObject的Type对应的对象是可以在不同的Application Domain之间传递呢。但是他们之间又会有怎样的差异呢?他们是真正的对象呢?还仅仅是位于新建Application Domain中的对象一个代理(Proxy)?我们通过调用定义在System.Runtime.Remoting中的静态方法: IsTransparentProxy。了解Remoting的人相信对这个方法不会感到陌生。他用于判断某个对象是否是一个Transparent Proxy(在当我们跨Application Domain远程调用一个Remote Object的时候,实际上我们并非直接调用Remote Object的方法,而是通过一个同Client处在同一个Application Domain的Transparent Proxy对象间接地调用远程对象——Transparent Proxy具有一个Remote Object的Reference,可以轻易地找到这个Remote Object。其实在真正的场景中,Client调用Transparent Proxy,Transparent Proxy再去调用Real Proxy,Real Proxy最终才去调用Remote Object——如果你想进一步地了解Remoting,你可以参照MSDN)

Console.WriteLine("\nmarshalByValueObject is a transparent proxy? {0}.",RemotingServices.IsTransparentProxy(marshalByValueObject)?"Yes":"No");
            Console.WriteLine("marshalByRefObject is a transparent proxy? {0}.", RemotingServices.IsTransparentProxy(marshalByRefObject) ? "Yes" : "No");

通过运行结果,我们可以看到:MarshalByValueType对象marshalByValueObject,IsTransparentProxy方法返回False。而对于MarshalByRefType对象marshalByRefObject则返回True。这就充分证明了,标记了System. SerializableAttribute属性的Type所对应的对象是一个真正意义上的对象,而对于继承自MarshalByRefObject Type,当该Type对应的对象从一个Application Domain传递到另一个Application Domain后,另一个Application Domain获得的仅仅是原来对象的Proxy而已。

我们可以从传递的机制来解释这种差异。当你把System. SerializableAttribute属性运用要某个Type,或者让某个Class实现System.Runtime.Serialization.ISerializable Interface的时候,你实际上是给该Type赋予了一种能力——一种可以序列化成XML的能力(XMLSerializer负责把对象序列化成XML)。当这种对象从一个Application Domain传递到另一个Application Domain的时候,Object先被序列化成XML,接着把XML传递到另一个Application Domain中,在新的Application Domain中,通过反序列化重新生成一个新的Object——这个新的Object和处于另一个Application Domain已经没有任何关系。

而对于而对于继承自MarshalByRefObject Type的对象,虽然他不能够序列化成XML,但是可以通过传递Reference的方式在Application Domain之间 传递。当这种传递实质上是通过在另一个Application创建一个拥有该对象引用的一个Proxy。而这个Proxy依赖一这个处理另一个Application Domain的真正对象。

5. 上面我们实际上已经说清楚了两个对象传递的差异——By Value 和By Reference。现在我们来进一步验证前面我们说的。我们继续来看看我们的代码:

AppDomain appDomain_MarshalByValueType = marshalByValueObject.GetAppDomain();
AppDomain appDomain_MarshalByRefType = marshalByRefObject.GetAppDomain();

            Console.WriteLine("\nThe method of marshalByValueObject is executed in the default application domain?\"{0}\"",
                 object.ReferenceEquals(AppDomain.CurrentDomain, appDomain_MarshalByValueType) ? "Yes" : "No");
            Console.WriteLine("The method of marshalByRefObject is executed in the default application domain?\"{0}\"",
                object.ReferenceEquals(AppDomain.CurrentDomain, appDomain_MarshalByRefType) ? "Yes" : "No");

我们通过调用连个对象的GetAppDomain()方法,从而获得真正执行该方法的Application Domain。然后再和当前的Application Domain进行比较。我们发现对于MarshalByValueType对象marshalByValueObject,真正执行操作是在当前的Application Domain中进行的。而对于MarshalByRefType对象marshalByRefObject,则是我们新建立的Application Domain。这充分证明了当marshalByValueObject传递到新的Application后,生成一个和原来对象一模一样的对象,这个对象具有执行自身操作的能力。而对于marshalByRefObject,由于它只是一个Proxy而已,他只有把对对象的操作请求发送给真正的,位于另一个Application Domain的真正对象(同时他也负责把远程对象的执行结果返回给调用者),真正的操作实际上是发生在远程对象的Application Domain。

由于marshalByRefObject,依赖于远程对象,所以当我们卸载掉Host远程对象的Application Domain,对marshalByRefObject的任何调用将变得无效。所以这里可以对下面这段代码作出解释。

AppDomain.Unload(appDomain_MarshalByRefType);
marshalByValueObject.GetAppDomain();

             try
            {
                marshalByRefObject.GetAppDomain();
            }
             catch (Exception ex)
            {
                Console.WriteLine("\nAn exception is thorwn when calling the method of marshalByRefObject because \"{0}\"", ex.Message);
            }

注:在分布式开发中,我们会大量接触到By Value 和By Refernce传递。一般而言,By Value用于商业实体的传递(Business Entity),而By Reference用于远程调用(RPC)或者是调用Service。


作者:蒋金楠
微信公众账号:大内老A
微博: www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
弹性计算 NoSQL 数据库
阿里云降价了!2024年3月阿里云产品大降价详细优惠内容介绍汇总
阿里云在2024年3月进行了一次大规模的云产品降价,降价幅度高达20%,部分产品的降价幅度甚至达到了55%。这次降价涵盖了多种云产品,包括云服务器ECS、云数据库RDS、云数据库Redis社区版、云数据库MongoDB、云数据库ClickHouse社区兼容版等。此外,阿里云还增加了对象存储OSS的请求免费额度,并降低了其按量付费和预留空间的官网折扣价。
694 2
|
数据采集 安全 搜索推荐
做相关外链有什么不好?
答案是:相关性外链会导致网站被惩罚! 理解外链的双刃剑性质 外链,特别是相关外链,对于Google优化策略是非常重要的。 然而,这种策略也带来了一些潜在的风险。 本文将探讨做相关外链可能导致的问题。 外链可能带来的风险 对搜索排名的影响 虽然高质量的外链可以提高网站的权威性和搜索排名,但过度或不当的外链建设可能会导致Google对您的网站进行处罚。 因此,选择与网站内容不相关或质量低下的外链可能会对您的Google优化努力产生负面影响。
196 0
做相关外链有什么不好?
《QT从基础到进阶·三十四》qobject_cast动态强制转换
《QT从基础到进阶·三十四》qobject_cast动态强制转换
1103 0
|
人工智能 大数据 UED
阿里云客户服务部总经理张颖杰:用心聆听,服务见智
如何应对全球百万级服务需求、如何保证用户体验、服务行业如果拥抱人工智能等问题一直以来是业界争论的热点问题。在12月20日科技界年度压轴大戏——2017云栖大会·北京峰会的“企业云上业务优化”专场上,阿里云客户服务部总经理张颖杰先生分享了阿里云服务面对上述问题时的解决方案。
|
Oracle 关系型数据库 数据库
ORACLE锁等待的处理方法
前言:锁等待的管理是数据库管理员在日常工作中会碰到较多的一个问题,一般来说大型的ERP锁等待的处理会相对较少,小型的应用系统锁等待会相对比较多。 常规的锁等待的处理方法如下: 1) 先查找持有锁的对象: 脚本:select a.
895 0
|
15天前
|
存储 弹性计算 人工智能
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
2025年9月24日,阿里云弹性计算团队多位产品、技术专家及服务器团队技术专家共同在【2025云栖大会】现场带来了《通用计算产品发布与行业实践》的专场论坛,本论坛聚焦弹性计算多款通用算力产品发布。同时,ECS云服务器安全能力、资源售卖模式、计算AI助手等用户体验关键环节也宣布升级,让用云更简单、更智能。海尔三翼鸟云服务负责人刘建锋先生作为特邀嘉宾,莅临现场分享了关于阿里云ECS g9i推动AIoT平台的场景落地实践。
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
|
6天前
|
云安全 人工智能 安全
Dify平台集成阿里云AI安全护栏,构建AI Runtime安全防线
阿里云 AI 安全护栏加入Dify平台,打造可信赖的 AI
|
9天前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
885 29