應用程序域基礎


應用程序域基礎

們都知道,進程是操作系統進行資源調度和分配基本單位,每個進程實際代表當前應用程序從啟動到結束全部過程。對於Windows每一個.exe文件,在運行時都要由一個進程來承載它。與非托管.exe文件不同是,托管.exe文件並沒有直接將程序集加載到當前進程當中,而是將程序集加載到應用程序域中,然后將應用程序域加載到進程中。每個進程可以承載多個應用程序域。因此,對於托管程序,每個進程可以承載多個應用程序,這同時也提升應用程序性能,因為進程切換所耗費性能要多於應用程序域切換。

 

 

 

1.1 應用程序域的特點

托管程序為什么要使用應用程序域呢?概括其優點如下:

1.        在一個應用程序中出現錯誤不會影響其應用程序。

2.        因為類型安全代碼不會導致內存錯誤,所以使用應用程序域可以確保在一個域中運行代碼不會影響進程中應用程序。

3.        能夠在不停止整個進程情況下停止單個應用程序。

4.        使用應用程序域時,可以卸載在單個應用程序中運行代碼。

5.        在一個應用程序中運行代碼不能直接訪問其應用程序中代碼或資源。

強制實施此隔離,公共語言運行庫禁止在不同應用程序域中對象之間進行直接調用。要在各域之間傳遞對象,可以通過復制這些對象,或通過代理訪問這些對象。如果復制對象,那么對該對象調用為本地調用。也就是說,調用方和被引用對象位於同一應用程序域中。如果通過代理訪問對象,那么對該對象調用為遠程調用。在此情況下,調用方和被引用對象位於不同應用程序域中。域間調用所采用遠程調用基礎結構與兩個進程間調用或兩台計算機間調用基礎結構相同。因此,被引用對象元數據必須對於兩個應用程序域均可用,以便用 JIT 正確編譯該方法調用。如果調用域對被調用對象元數據沒有訪問權,則編譯可能失敗,並引發類型為 System.IO.FileNotFound 異常。

1.        代碼行為作用范圍由它運行所在應用程序決定。

換言之,應用程序域將提供應用程序版本策略等配置設置、它所訪問任意遠程程序集位置,以及加載到該域中程序集位置信息。

2.        向代碼授予權限可以由代碼運行所在應用程序域來控制。

1.2 創建應用程序域

.NET提供相關類和方法來獲取當前應用程序域基本信息,也提供創建和配置應用程序域成員。其中,AppDomain 類是應用程序域編程接口,此類包括各種方法,這些方法可以創建和卸載域、創建域中各類型實例以及注冊各種通知(如應用程序域卸載)。對於應用程序域卸載,將在第3.1.3節做介紹。

 

代碼清單1-1演示如何創建一個應用程序域。

代碼清單1-1 創建應用程序域

class Program

    {

 

        static void Main(string[] args)

 

        {

 

           AppDomain myDomain= AppDomain.CreateDomain("xuanhunDomain");//創建名為xuanhunDomain應用程序域

           Console.WriteLine("myDomain name is :{0}",myDomain.FriendlyName);//輸出創建程序域名稱

           Console.WriteLine("當前程序域名稱是:{0}", AppDomain.CurrentDomain.FriendlyName);//輸出當前程序域名稱

           Console.ReadKey();

 

        }

 

    }

 

輸出結果如圖1-1所示。

image

1-1 輸出應用程序域名稱

 

1.3 卸載應用程序域

當完成使用應用程序域時,可使用System.AppDomain.Unload方法將其卸載。Unload 方法會正常關閉指定應用程序域。卸載過程中,沒有新線程可以訪問該應用程序域,並且會釋放該應用程序域特定所有數據結構。加載到應用程序域中所有程序集都會被移除,無法再使用。如果應用程序域中程序集不是特定於域,則程序集數據會保留在內存中,直到整個進程關閉。除關閉整個進程,沒有機制可以卸載非特定於域程序集。在某些情況下,卸載應用程序域請求不起作用,並導致CannotUnloadAppDomainException。代碼清單1-2在代碼清單1-1基礎上添加卸載xuanhunDomain程序域語句,並且在卸載后再次嘗試輸出該應用程序域名稱,這將引發CannotUnloadAppDomainException

代碼清單1-2 卸載應用程序域

class Program

    {

 

        static void Main(string[] args)

 

        {

 

           AppDomain myDomain= AppDomain.CreateDomain("xuanhunDomain");

 

           Console.WriteLine("myDomain name is :{0}",myDomain.FriendlyName);

 

           Console.WriteLine("當前程序域名稱是:{0}", AppDomain.CurrentDomain.FriendlyName);

 

           AppDomain.Unload(myDomain);

 

           try//試圖訪問被卸載應用程序域

           {

 

               Console.WriteLine("myDomain name is :{0}", myDomain.FriendlyName);

 

           }

 

           catch (CannotUnloadAppDomainExceptione)

 

           {

 

               Console.WriteLine(e.Message);

 

           }

 

           Console.ReadKey();

 

}

 

輸出結果如圖1-2所示。

image

1-2 卸載應用程序域

 

將程序集加載到應用程序域方法已經在第2章中做介紹,這里就不再重復。下面接着討論如何獲得當前線程應用程序域相關信息,如代碼清單1-3所示。

代碼清單1-3 獲得當前線程應用程序域相關信息

public void GetDomainInfo()

 

        {

 

            ActivationContext tContext = AppDomain.CurrentDomain.ActivationContext;//獲取上下文信息

       ApplicationIdentity tIdentity=AppDomain.CurrentDomain.ApplicationIdentity;//獲取應用程序標識

         

 

            System.Security.Policy.ApplicationTrust tTrust = AppDomain.CurrentDomain.ApplicationTrust;//獲取當前程序信任級別

            string tDirectory = AppDomain.CurrentDomain.BaseDirectory;// 獲取基目錄,它由程序集沖突解決程序用來探測程序集

            AppDomainManager tDomainManager = AppDomain.CurrentDomain.DomainManager;//獲得初始化應用程序域時主機提供域管理器

            string tDynamicDirectory = AppDomain.CurrentDomain.DynamicDirectory;//獲取目錄,它由程序集沖突解決程序用來探測動態創建程序集

            System.Security.Policy.Evidence tEvidence = AppDomain.CurrentDomain.Evidence;//獲取與此應用程序域相關聯 Evidence,它用做安全策略輸入

            string tFrindlyName = AppDomain.CurrentDomain.FriendlyName;//獲取此應用程序域友好名稱

            int tId = AppDomain.CurrentDomain.Id;//獲得一個整數,該整數唯一標識進程中應用程序域

            bool tIsFullTrusted = AppDomain.CurrentDomain.IsFullyTrusted;//表示當前應用程序域中程序集是否為完全信任級別

            bool tIsHomogenous = AppDomain.CurrentDomain.IsHomogenous;//獲取一個值表示是否擁有對加載到當前應用程序域所有程序集權限集合

            long tMSMemorySize = AppDomain.CurrentDomain.MonitoringSurvivedMemorySize;

 

            long tMTAMemorySieze = AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize;

 

            TimeSpan tMTPTime = AppDomain.CurrentDomain.MonitoringTotalProcessorTime;

 

            System.Security.PermissionSet tPermissionSet = AppDomain.CurrentDomain.PermissionSet;//獲取權限集

            string tRPath = AppDomain.CurrentDomain.RelativeSearchPath;//獲取相對於基目錄路徑,在此程序集沖突解決程序應探測專用程序集

            AppDomainSetup tASetup = AppDomain.CurrentDomain.SetupInformation;//安裝信息

            bool tSCopyFiles = AppDomain.CurrentDomain.ShadowCopyFiles;//獲取一個指示值,它表明加載到應用程序域中所有程序集是否為影像復制

}

 

在代碼清單1-3中,使用AppDomain.CurrentDomain的屬性來獲取當前應用程序域的實例,可以從中獲取當前應用程序域的相關信息,其中.NET 4.0中新增的屬性如下:

q  AppDomain.CurrentDomain.MonitoringSurvivedMemorySize。獲取上次完全阻止回收后保留下來的、已知由當前應用程序域引用的字節數。

q  AppDomain.CurrentDomain.MonitoringTotalAllocatedMemorySize。獲取自從創建應用程序域后由應用程序域進行的所有內存分配的總大小(以字節為單位,不扣除已回收的內存)。

q  AppDomain.CurrentDomain.MonitoringTotalProcessorTime。獲取自從進程啟動后所有線程在當前應用程序域中執行時所使用的總處理器時間。

q  AppDomain.CurrentDomain.PermissionSet。獲取沙箱應用程序域的權限集。

----------------注,本文部分內容改編自《.NET 安全揭秘》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM