欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
從高級源碼到機器碼的過(guò)程,反射DLL加載卸載

在Java中有虛擬機,代碼運行時(shí)虛擬機把Java語(yǔ)言編譯成與機器無(wú)關(guān)的字節碼,然后再把字節碼編譯成機器指令執行,那么在.NET中程序是如何運行的呢?

其實(shí)運行原理是一樣的,.NET中的虛擬機是CLR(公共語(yǔ)言運行時(shí)),無(wú)論是C#程序還是VB程序,首先會(huì )由CLR編譯成與平臺無(wú)關(guān)的中間語(yǔ)言IL,然后由公共語(yǔ)言運行時(shí)CLR的

即時(shí)編譯器JIT編譯成機器代碼,再由CPU去執行它。所以說(shuō).NET程序也是需要二次編譯才能運行,其中涉及的相關(guān)術(shù)語(yǔ)解釋如下:

  1. IL/MSIL (Microsoft Intermediate Language) :微軟中間語(yǔ)言 ,IL是MSIL的縮寫(xiě),譯為中間語(yǔ)言,.NET程序下的所有語(yǔ)言都會(huì )編譯成中間語(yǔ)言,所以他們之間可以相互調用,與語(yǔ)言無(wú)關(guān);
  2. CTS (Common Type System):通用的數據類(lèi)型系統,比如C#調用VS語(yǔ)言程序,雖然他們各自的數據類(lèi)型定義不一樣,但是最終都會(huì )轉化為通用類(lèi)型,比如c#中的int,VB語(yǔ)言中的integer,在CLS中都會(huì )轉化為System.int32,所以這兩者之間的程序可以相互調用;
  3. CLS(Common Language Specification):公共語(yǔ)言規范;
  4. CLR (Common Language Runtime):公共語(yǔ)言運行時(shí),也有的叫公共語(yǔ)言運行庫;
  5. JIT (Just in time):即時(shí)編譯器。

 對于計算機來(lái)講,它只認識01010101之類(lèi)的二進(jìn)制代碼,人類(lèi)寫(xiě)的高級語(yǔ)言(如C#、JAVA等)計算機是沒(méi)法識別的,所以需要將高級語(yǔ)言轉化為01讓計算機可以識別的二進(jìn)制編碼,中間是有一個(gè)過(guò)程的。就拿C#來(lái)講,VS編譯器會(huì )將編寫(xiě)好的代碼進(jìn)行編譯,編譯后會(huì )生成exe/dll文件,.Net Core里面已經(jīng)不生成exe了,都是dll。dll和exe還需要CLR/JIT的即時(shí)編譯成字節碼,才能最終被計算機執行。有伙伴就會(huì )問(wèn)為什么要編譯2次呢,先編譯到dll,再編譯到字節碼01呢,為什么不能一次性編譯成字節碼呢?因為我們寫(xiě)的是C#語(yǔ)言,但是真實(shí)運行的機器有很多種,可能是32位,也可能是64位,操作系統可能是windows、linux、unix等,不同的計算機不同的操作系統識別字節碼的可能是不一樣的,但是從高級語(yǔ)言編譯成exe/dll這一步是一樣的。所以只要在不同運行環(huán)境的計算機上安裝對應的不同的CLR/JIT,就可以運行我們同一個(gè)exe/dll了。這里就大概講下這樣一個(gè)過(guò)程,后面會(huì )有章節詳細講解程序如何被計算機執行的?,F在我們先關(guān)注編譯生成的exe/dll,它包含2部分,分別是中間語(yǔ)言IL和源數據元數據metadata。IL里面包含我們寫(xiě)的大量的代碼,比如說(shuō)方法、實(shí)體類(lèi)等。元數據metadata不是我們寫(xiě)的代碼,它是編譯器在編譯的時(shí)候生成的描述,它可能是把命名空間、類(lèi)名、屬性名記錄了一下,包括特性。

CLR VS JVM

以 Java 為例,Java 編譯后產(chǎn)生的并不是一個(gè)可執行的文件,而是一個(gè) ByteCode (字節碼)文件,里面包含了從 Java 源代碼轉換成等價(jià)的字節碼形式的代碼。Java 虛擬機(JVM)負責執行這個(gè)文件。

虛擬機執行中間代碼的方式分為 2 種:解釋執行和 JIT(即時(shí)編譯)。解釋執行即逐條執行每條指令,JIT 則是先將中間代碼在開(kāi)始運行的時(shí)候編譯成機器碼,然后執行機器碼。由于執行的是中間代碼,所以,在不同的平臺實(shí)現不同的虛擬機,都可以執行同樣的中間代碼,也就實(shí)現了跨平臺

C# 和 Java 類(lèi)似,C# 會(huì )編譯成一個(gè)中間語(yǔ)言(CIL,Common Intermediate Language,也叫 MSIL),CIL 也是一個(gè)高級語(yǔ)言,而運行 CIL 的虛擬機叫 CLR(Common Language Runtime)。通常我們把 C#、CIL、CLR,再加上微軟提供的一套基礎類(lèi)庫稱(chēng)為 .Net Framework。

C# 源代碼到機器碼過(guò)程:

1、源代碼——2、編譯器(vs自帶的csc.exe,還有mono的mcs.exe,【java編譯器javac.exe】)——3、IL中間語(yǔ)言字節碼——4、CLR啟動(dòng)JIT即時(shí)編譯——5、將IL編譯為可以真正在CPU上運行的機器碼。

編譯時(shí)【工具:編譯器】:步驟1 到 步驟3,編譯源代碼

運行時(shí)【工具:CLR】:步驟3到步驟5。編譯IL

運行時(shí)就是代碼跑起來(lái)了.被裝載到內存中去了.(你的代碼保存在磁盤(pán)上沒(méi)裝入內存之前是個(gè)死家伙.只有跑到內存中才變成活的).

中間語(yǔ)言IL

中間語(yǔ)言【IL】有時(shí)也稱(chēng)為公共中間語(yǔ)言(CIL:Common Intermediate Language) 或 Microsoft中間語(yǔ)言(MSIL),也可叫做字節碼。

之所以叫公共的,可以理解為 就是可以被不同平臺【操作系統】上識別,所以才可移植。

IL我們是看不懂的,因為他是二進(jìn)制的,

我們說(shuō)的學(xué)習并分析IL并不是IL,而是由IL這種匯編語(yǔ)言【相當于.Net平臺的匯編語(yǔ)言,類(lèi)似于Windows平臺的匯編語(yǔ)言】編寫(xiě)的代碼,我們可以看懂,JIT不能直接運行我們使用IL匯編語(yǔ)言寫(xiě)的代碼,JIT運行的是IL匯編語(yǔ)言編譯成的IL代碼【二進(jìn)制字節碼】,編譯器不是編譯源碼的csc.exe,也不是編譯IL為機器碼的JIT即時(shí)編譯器而是,ilasm.exe即IL匯編程序,對應的還有ildasm.exe IL反匯編程序

PE文件

PE文件的全稱(chēng)是Portable Executable,意為可移植的可執行的文件,常見(jiàn)的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微軟Windows操作系統上的程序文件(可能是間接被執行,如DLL)

托管代碼

托管代碼(C#源代碼,VB源代碼,F#等,C/C++是非托管)

為什么叫托管呢?

是因為可被編譯器編譯為中間語(yǔ)言,是受管于CLI式的內存管理和線(xiàn)程安全管理的。

那為什么CLR可以管理呢?

是由CLR啟動(dòng)的JIT編譯IL為機器碼,這樣,CLR就 能確切的知道代碼的作用,并可以有效的管理代碼。

非托管代碼

非托管代碼,直接編譯成目標計算機碼,在公共語(yǔ)言運行庫環(huán)境的外部,由操作系統直接執行的代碼,代碼必須自己提供垃圾回收,類(lèi)型檢查,安全支持等服務(wù)。如需要內存管理等服務(wù),必須顯示調用操作系統的接口,通常調用Windows SDK所提供的API來(lái)實(shí)現內存管理。

托管代碼和非托管代碼的區別:

  1、托管代碼是一種中間語(yǔ)言,運行在CLR上;非托管代碼被編譯為機器碼,運行在機器上。

  2、托管代碼獨立于平臺和語(yǔ)言,能更好的實(shí)現不同語(yǔ)言平臺之間的兼容;非托管代碼依賴(lài)于平臺和語(yǔ)言。

  3、托管代碼可享受CLR提供的服務(wù)(如安全檢測、垃圾回收等),不需要自己完成這些操作;非托管代碼需要自己提供安全檢測、垃圾回收等操作。

字節碼和機器碼

字節碼(Byte-code)是一種包含執行程序,由一序列 op 代碼/數據對組成的二進(jìn)制文件,是一種中間碼。字節碼文件是一種和任何具體機器環(huán)境及操作系統環(huán)境無(wú)關(guān)的中間代碼,所以可以移植不同平臺執行。

例如:java的虛擬機編譯的java字節碼,以.class結尾的文件。IL,相當于java的字節碼,也是一種中間語(yǔ)言。

機器碼

計算機直接使用的程序語(yǔ)言,其語(yǔ)句就是機器指令碼,機器指令碼是用于指揮計算機應做的操作和操作數地址的一組二進(jìn)制數。 機器碼就是諸如0101010100......的二進(jìn)制數

1,機器碼本質(zhì)就是一個(gè)二進(jìn)制數位:"0"和“1”。

2,8位單片機如十六制數0x55,機器碼:01010101。

3,16位單片機如十六制數0xaaaa,機器碼:1010 1010 1010 1010。

4,32位ARM如十六制數0x5555aaaa,機器碼:

01010101010101010101010101010101

————————————————

二進(jìn)制格式【字節碼】文件:DB 0F 49 40

【機器碼】:1010等二進(jìn)制數。

CLI

每種變成語(yǔ)言都有一組內置的類(lèi)型,用來(lái)表示如整數、浮點(diǎn)數和字符等之類(lèi)的對象。過(guò)去,這些類(lèi)型的特征因變成語(yǔ)言和平臺的不同而不同。例如,組成整數的位數對于不同的語(yǔ)言和平臺就有很大差別。

  然而,這種同一性的缺乏使我們難以讓使用不同語(yǔ)言編寫(xiě)的程序及庫一起良好協(xié)作。為了有序協(xié)作,必須有一組標準。

  CLI(Common Language Infrastructure,公共語(yǔ)言基礎結構)就是這樣一組標準,它把所有.NET框架的組件連結成一個(gè)內聚的、一致的系統。它展示了系統的概念和架構,并詳細說(shuō)明了所有軟件都必須堅持的規則和約定。

DotNet程序執行流程

.NET 應用程序源代碼被編譯為 Microsoft 中間語(yǔ)言 (MSIL),也稱(chēng)為中間語(yǔ)言 (IL) 或通用中間語(yǔ)言 (CIL)。.NET 和非 DOTNET 應用程序在編譯應用程序時(shí)生成程序集。通常,程序集具有 的擴展 .DLL 或 .EXE 基于我們編譯的應用程序類(lèi)型。
例如,如果我們在 .NET 中編譯窗口或控制臺應用程序,我們會(huì )獲得類(lèi)型的程序集.EXE,而當我們在 .NET 中編譯 Web 或類(lèi)庫項目時(shí),我們得到一個(gè)類(lèi)型的程序集.Dll。

.NET 和 NON-DOTNET 程序集的區別在于 DOTNET 程序集是中間語(yǔ)言格式,而非 .NET程序集是本機代碼格式。

NON.NET 應用程序可以直接在操作系統上運行,因為 NON-DOTNET 程序集包含本機代碼,
而 .NET應用程序在稱(chēng)為通用語(yǔ)言運行時(shí) (CLR)的虛擬環(huán)境的頂部運行。
CLR 包含一個(gè)名為"實(shí)時(shí)編譯器 (JIT)"的組件,該組件將中間語(yǔ)言轉換為本機代碼,基礎操作系統可以理解該代碼。

DotNet程序執行步驟

在 .NET 中,應用程序執行包含 2 個(gè)步驟
在步驟1中,相應的語(yǔ)言編譯器將源代碼編譯為中間語(yǔ)言(IL),在第二步中,CLR中的JIT編譯器將中間語(yǔ)言(IL)代碼轉換為本機代碼,然后可由底層操作系統執行本機代碼。 下圖顯示了上述過(guò)程。

由于 .NET 程序集采用中間語(yǔ)言 (IL) 格式,而不是本機代碼或計算機代碼格式,因此只要目標平臺具有通用語(yǔ)言運行時(shí) (CLR),.NET 程序集便可移植到任何平臺。目標平臺的 CLR 將中間語(yǔ)言代碼轉換為基礎操作系統可以理解的本機代碼或計算機代碼。

中間語(yǔ)言代碼也稱(chēng)為托管代碼。這是因為 CLR 管理在它內部運行的代碼。例如,在 VB6 程序中,開(kāi)發(fā)人員負責取消分配對象消耗的內存。如果程序員忘記去分配內存,則可能會(huì )發(fā)生內存異常。另一方面,.NET 程序員不必擔心取消分配對象消耗的內存。自動(dòng)內存管理也稱(chēng)為垃圾回收,由 CLR 提供。由于 CLR 正在管理和執行中間語(yǔ)言,因此它 (IL) 也稱(chēng)為托管代碼。

.NET 支持不同的編程語(yǔ)言,如 C#、VB、J# 和C++。C# 、VB 和 J# 只能生成托管代碼 (IL),而 C++可以生成托管代碼 (IL) 和非托管代碼(本機代碼)。

關(guān)閉程序后,本機代碼不會(huì )永久存儲在任何地方,本機代碼將被扔掉。當我們再次執行程序時(shí),將再次生成本機代碼。

.NET 程序類(lèi)似于 java 程序執行。在 Java 中,我們有字節碼和 JVM(Java 虛擬機),而在 .NET 中,我們有中間語(yǔ)言和 CLR(通用語(yǔ)言運行時(shí))。

反射加載dll,讀取module、類(lèi)、方法、特性

 

反射就是讀取metadata里面的數據的,然后去使用它。接下來(lái)通過(guò)反射的方式去實(shí)現調用DSqlServerHelper類(lèi)中的查詢(xún)方法Query:

 我們想在Program的Main方法中調用DB.SqlServer類(lèi)庫中SqlServerHelper類(lèi)中的查詢(xún)方法Query。以往實(shí)現這種功能都是在MyReflection的控制臺程序中引用DB.SqlServer和DB.Interface類(lèi)庫,才能調用Query方法

現在我們不引用通過(guò)反射的方式

 可以從圖中結果看出利用反射成功調用了DSqlServerHelper類(lèi)下的查詢(xún)方法Query。對比下最開(kāi)始添加引用直接new SqlServerHelper()對象然后調取Query方法寫(xiě)的代碼更少些,而利用反射需要多寫(xiě)好幾行代碼,貌似反射更麻煩些,那什么還要用反射呢?如果把using DB.SqlServer注釋掉,就會(huì )發(fā)現new SqlServerHelper()會(huì )報錯,而不會(huì )影響反射寫(xiě)的代碼。也就是說(shuō)反射在不添加引用,不new一個(gè)對象的情況下,可以動(dòng)態(tài)的調取對象中的方法,這就是反射的好處。

c#中通過(guò)反射可以方便的動(dòng)態(tài)加載dll程序集,但是如果你需要對dll進(jìn)行更新,卻發(fā)現.net類(lèi)庫沒(méi)有提供卸載dll程序集的方法。在.net 中,加入了應用程序域的概念,應用程序域是可以卸載的。也就是說(shuō),如果需要對動(dòng)態(tài)加載的dll程序集進(jìn)行更新,可以通過(guò)以下方法解決:

新建一個(gè)應用程序域,在該應用程序域中動(dòng)態(tài)加載DLL,然后可以卸載掉該應用程序域。該應用程序域被卸載的時(shí)候,相關(guān)資源也會(huì )被回收。

要想這樣實(shí)現,就要讓你程序的currentDomain和新建的newDomain之間進(jìn)行通信,穿過(guò)應用程序域的邊界。

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Threading; 
using System.Reflection; 
namespace UnloadDll 
{ 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            string callingDomainName = AppDomain.CurrentDomain.FriendlyName; 
            AppDomain ad = AppDomain.CreateDomain("DLL Unload test"); 
            ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap(@"UnloadDll.exe", "UnloadDll.ProxyObject"); 
            obj.LoadAssembly(); 
            obj.Invoke("loadDllName.ClassName", "methodName", "It's a parameter"); 
            AppDomain.Unload(ad); 
            obj = null; 
            Console.ReadLine(); 
        } 
    } 
    class ProxyObject : MarshalByRefObject 
    { 
        Assembly assembly = null; 
        public void LoadAssembly() 
        { 
            assembly = Assembly.LoadFile(@"loadDllName.dll");            
        } 
        public bool Invoke(string fullClassName, string methodName, params Object[] args) 
        { 
            if(assembly == null) 
                return false; 
            Type tp = assembly.GetType(fullClassName); 
            if (tp == null) 
                return false; 
            MethodInfo method = tp.GetMethod(methodName); 
            if (method == null) 
                return false; 
            Object obj = Activator.CreateInstance(tp); 
            method.Invoke(obj, args); 
            return true;            
        } 
    } 
} 
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
C#學(xué)習筆記(一)——軟件構建與.NET平臺
簡(jiǎn)單介紹托管執行和 CLI
NET基礎
不依賴(lài).Net的可以調用托管代碼的非托管代碼
NET程序是如何編譯的
CLR VIA C#之旅(1):品味細節,CLR的執行模型
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久