Board logo

主題: [轉貼] .NET 觀念深入淺出與工具介紹 [打印本頁]

發表人: jocosn    時間: 2005-4-5 11:41 PM     主題: [轉貼] .NET 觀念深入淺出與工具介紹

.NET 10個必備開發工具
1.NUnit  編寫單元測試的工具
2.NDoc  自動生成代碼文檔的工具
3.NAnt   編譯解決方案的工具
4.CodeSmith  自動生成代碼的工具
5.FxCop  檢查你的代碼是否按照規范編寫的工具
6.Snippet Compiler  編譯少量代碼的工具
7.ASP.NET Version Switcher  Visual Studio .NET Project Converter Regulator VS.Net不同版本的轉換器
8..NET Reflector  

工具网站:
http://dotnettoolbox.com/toolbox/


三種以C#開發的Blog
因為實在是很好奇,到底有哪幾種Blog會以C#開發,所以特地找了一下,發現原來還有另外兩種,以下轉貼了他們的超連結以及簡介
1.tBlogger
   tBlogger provides a complete blog site written in C# with ASP.NET that uses XML as a backend.

2. Dot Text
   .Text is a powerful blogging engine that is used to host hundreds of blogs. The application is an example of an N-tiered application.

3. DasBlog
dasBlog, an evolution of the BlogX weblog engine, adds lots of additional features like Trackback, Pingback, Mail notifications, full Blogger/MovableType API support, Comment API support, fully customizable Radio-style templates, Mail-To-Weblog/POP3 with attachment and embedded picture support, web-based DHTML editing, web-based OPML editor, web-based configuration editing, and other goodies to the BlogX codebase

ASP.NET 產生的 ViewState 解析
http://www.wilsondotnet.com/Demos/ViewState.aspx

[jocosn 在 2005-4-16 04:51 PM 作了最後編輯]
發表人: spurslee1    時間: 2005-4-15 04:10 AM

感謝分享~
最近也在摸.Net
發表人: jocosn    時間: 2005-4-16 03:55 PM

.NET               --摘錄自「Visual Basic.NET程式設計經典」一書,為推廣 .NET 轉載如下

1. 組件 (Assembly)
  程式原始碼在經過 IL (Intermediate Language) 編譯器編譯後,會產生一個副檔名為 exe 或 dll 的檔案 (我們稱之為「組件」、Assembly),但是這並不是真正可以直接由CPU執行的檔案,因為 IL 編譯器只是將原始程式碼編譯成一個中間碼,我們稱為MSIL (Microsoft Intermediate Language),這種IL必須再經過第二次編譯後才會產生真正可以由CPU執行的執行檔,這一點有些類似Java,Java原始程式碼在經過編譯之後會產生中間碼 *.class,我們稱之為 byte code,這個byte code類似 .NET中的Assembly,也是不能直接執行的,必須再透過Java的虛擬機器 (Java Virtual Machine、VM) 來解譯執行,也就是一行一行翻譯成機器碼,然後由虛擬機器來執行。
  在組件中除了程式碼IL部份之外,尚包含了程式所需要的相關資源 (Resource),例如圖示、文字…等,除此之外在 Assembly中 還包含了一份Metadata,所謂的Metadata指的是用來描述該Assembly的資訊,例如版本、所需類別程式庫…等,因此只要一個Assembly就可以包含所有需要的程式、資源、以及自我描述資訊,也就是說Assembly不再需要如同COM元件一樣必須在系統登錄 (Registry) 中註冊,也免除了以往不同版本COM元件在Registry中的註冊資訊衝突的問題。

2. JIT 編譯器 (Just-In-Time Compiler)
  由於組件並不是真正的可執行檔,因此在執行之前必須先進行第二次編譯,這部份就由 JIT 編譯器來負責,當我們第一次執行某一個組件時,組件載入器 (Assembly Loader) 會負責將組件載入,並檢查該組件是否有編譯的權限、以及相關的安全性原則,然後交由 JIT 編譯器來進行編譯,JIT編譯器就開始將組件中的 IL 編譯成真正的可執行機器碼 Native Code,如果該組件引用了其它類別程式庫,則由類別載入器 (Class Loader) 將所需的類別程式庫一併載入編譯。

3. Native Code Manager
  編譯後產生的Native Code則交由 Native Code Manager 來管理,Native Code Manager 會進行 Native Code 的快取,因此第二次再執行某一個組件時,就直接執行快取中的Native Code,不用再由JIT編譯器進行編譯動作,因此第二次以後的執行速度會非常快,這一點和Java就不同了,Java不論第幾次執行,都必須經過Java虛擬機器一行一行解譯執行,因此速度上會慢很多,而Native Code就是CPU可執行的機器碼,可以直接由CPU執行,不需要任何解譯,因此執行速度會快很多。
  當然如果想要事先先將組件編譯成Native Code也是可以的,這樣可以避免使用者第一次執行時比較慢的問題 (因為要由JIT編譯器編譯成Native Code),您只要開啟「開始/程式集/Microsoft Visual Studio .NET/Visual Studio .NET工具/Visual Studio .NET命令提示字元」,然後下達以下指令即可:
    語法: ngen.exe 組件檔案路徑與名稱
    例如: ngen c:\test.exe

4. 垃圾收集 (Garbage Collection)
  以往在程式中免不了要配置並使用記憶體,於是經常會使用到記憶體指標 (Pointer) 或者參考 (Reference),當記憶體使用完畢後,還要記得將記憶體歸還給作業系統 (或說「釋放 (Release)」出來),如果忘記釋放記憶體,那麼隨著程式的不斷執行,系統可用的記憶體會愈來前少 (只借不還嘛),最後導致記憶體不足而當機,因此程式設計師就必須自行對記憶體的使用多加注意。
  在 .NET 中提供了垃圾收集的機制 (Java中也有類似的機制),只要是沒有使用到的記憶體,.NET Framework會在適當的時機將這些記憶體回收給其它需要的組件使用,因此程式設計師對於記憶體使用就可以非常方便,要用的時候宣告一下,不用的時候就由 .NET Framework自動回收,不會造成記憶體漏失的狀況。

5. 例外管理員 (Exception Manager)
  當程式中出現錯誤,例如除以零、寫入磁片時磁碟機中找不到磁片…等狀況,就會產生例外 (Exception),以往在不同程式語言或軟體平台上處理錯誤的方式都不盡相同,例如Visual Basic使用On Error Goto … 、C++ 使用 try … catch …、Windows API使用HRESULT傳回錯誤代碼…,但是在 .NET中統一了錯誤處理機制,不論是使用那一種程式語言,例外狀況都由Exception Manager統一做管理,因此在C# 副程式中產生的例外狀況就可以在Visual Basic主程式中進行處理,完全可以做到跨語言的例外處理。

6. 執行緒支援 (Thread Support)
  在 .NET Framework中直接支援多執行緒 (Multi-Threads) 程式的開發,包含執行緒的建立、使用、暫停、結束,都可以在不同語言中獨立實作出來。

7. COM元件整合 (COM Interop)
  由於組件的執行環境與傳統COM元件不同,因此如果組件中需要引用到一個COM元件,就必須進行轉換,在 .NET 中使用 COM Interop 技術來達成這樣的目的,簡單來說,COM Interop做的只是使用一個 .NET 的類別將原本的 COM 元件包裝起來,讓組件誤以為所引用的是另一個組件,這項工作如果在Visual Studio .NET整合環境下做,就只需要直接將COM元件自系統登錄中引用進來,Visual Studio .NET會自動幫我們做 COM Interop。
  也就是說原本使用舊技術開發出來的 COM 元件,在 .NET Framework中可以繼續延用,並不會浪費原有的投資,另外新的組件也可以透過 COM+ 元件服務 (Component Service) 的機制,讓舊有的程式引用,如此新舊程式可以相互支援,各取所長。

8. 偵錯引擎 (Debug Engine)
  透過CLR中的偵錯引擎,我們可以在 .NET 平台上進行跨語言的程式偵錯,也就是說專案中的各個子系統可以用不同的程式語言來撰寫,然後統一透過 CLR 進行偵錯,這樣大大的節省了專案偵錯與維護上所需的成本。

[jocosn 在 2005-4-16 03:59 PM 作了最後編輯]
發表人: jocosn    時間: 2005-4-16 04:12 PM

http://www.computertoday.com.hk/computing.php?gsel=6&cid=91
整理如下

基本觀念註解
1) CLR的定位
 .NET應用程式的執行時期環境(Run-time)
 提供.NET應用程式和底層作業系統的中間層
2) Windows上的可執行檔(PE/COFF)
 A> .NET 程式都是標準 PE 格式的 exe 檔(這裏面存的不是 Native Code!!)。
 B> Windows上的可執行檔都必須遵循PE/COFF格式(Portable Excutable/Microsoft Common Object File Format)。
   標準的PE可執行檔分成二大部份
    * headers
    * native image sections(.data,.rdata,.rsrc,.text)
 C> .NET的可執行檔(.NET PE)
   為了可擴充性,Microsoft允許除了這些區段之外,在PE中自定新的section。
   安裝.NET時,會將OS的loader換掉,換成認得.NET PE的loader。
   .NET正是利用擴充section的方式,.NET的windows loader認得.NET PE,並將這些
   sections交由CLR處理。
   這就是為何.NET應用程式也可以以.exe方式存在並直接執行的原因。
 D> 觀察.NET的可執行檔
   利用dumpbin.exe可以dump出PE檔案。
3) .NET中deploy是以assembly為最小單位。
4) .NET的可執行檔中含MSIL及metadata。
  Microsoft的作品為了體貼使用者,隱藏了許多細節,對Developer來說,反而較不直觀。
  也是觀念不清的來源。
5) .NET Deployment 特色
 A> Side by side excution
   Any versions of the same shared assembly to execute at the same time,on
   the same system,even in the same process。
   (在同一個Process或系統中,不同版本的同名Dll檔案可以同時被存在並被執行)。
 B> Xcopy deployment
   Assembly具有自我描述功能,所以免註冊。
   為何具有自我描述功能?以assembly中的metadata來取代registry功能。
6) Managed Compiler
 指將.NET語言compile成「abstract intermediate form」的工具。
 如VB.NET的vbc.exe, VC#.NET的csc.exe等。

 abstract intermediate form包括二部份
  ﹡Metadata(描述程式之結構及相關資訊)
  ﹡Managed code(MSIL)
   Managed指由CLR來管理及執行的程式碼。
   Managed Code有三個部份由CLR來管理
     1> Type control:檢查型別、轉換型別。
     2> Exception Handling
     3> GC(記憶體回收)

7) Assembly & Module 觀念
 Assembly
  .NET中Deploy及Versioning的最小單位。
  指一個功能完整的.NET應用程式。(managed)

 Module
  泛指一個可.NET執行檔(.exe)、.NET library(.dll)或其它資源。(必須為managed code)
  藉由metadata描述和其它modules的關係。
  一個Assembly可以只包含一個或多個Modules。

 Assembly程式進入點所在稱為Prime Module。
8) Manifest
 Manifest就是Assembly的metadata。
 Manifest內含資訊
   ﹡assembly相依程式碼的位置
   ﹡組成assembly的各檔案檔名
   ﹡Assembly相依程式碼的metadata
   ﹡assembly的版本資訊
   ﹡型別資訊

9) Assembly Identities
 在COM時代,使用GUID來做為Component的唯一識別碼。但一長串的數字實在不容易記。
 .NET的private assembly引進namespace的觀念來做唯一識別(類似Java的Package)。但
 仍不能區分同一支程式的不同版本。
 因此,若一個assembly要由其它的.NET程式共享時,必須由Strong Name來做識別。
 
10) Strong Name
 A> .NET中的唯一識別採用 PKC (public key cryptography)
 B> Strong name 的認証過程
   1> Application creator利用assembly中的「manifest」做出一個hash code,我們稱之「original hash」。
   2> 利用private key 將「original hash」 加密成「encrypted hash」。
   3> 「Encrypted hash」及Application creator的「public key 」隨著assembly的manifest發行。
   4> 執行者以Application creator的「public key 」對「Encrypted hash」做解密,得到「original hash」 。
   5> 執行者以assembly中「manifest」做出一個「original hash」
   6> 執行者比對這二個「original hash」一不一致。

11) Shared Assembly
 GAC(Global Assembly Cache)
   放置重要的系統共享檔案
   有可能帶來和傳統registry一樣的問題。

 建議只在二種情況之下將assembly設為shared assembly
   這個assembly一定要被好幾個Application 所共用。
   這個assembly需要高安全性。(只有administrator可以動GAC中的檔案)

12) VEE結構
  Class Loader
    OS loader認出.NET PE後,將控制權交給CLR。此時ClassLoader會起來,找到並載入含進入點Main()的Class。
    其它的Classes在第一次被參考到時也會被載入。
    ClassLoader如何找到Classes: 目前目錄之.config、GAC及metadata(manifest)。

13) Method stub
  Class Loader將classes放入記憶體中後,會在每個class的method加上一個stub,這個stub有二個作用:
    ﹡用來辨別這個method是否已被JIT Compilation。
    ﹡標明這個是managed/unmanaged code

14) JIT Compiler
 .NET PE中所包含的不是native code,而是metadata及IL。
 直到method第一次被執行前才會由JIT將IL轉成managed native code。(如何得知第一次被執行?利用method stub)
 Compile完後將method的native code之位址存回method stub中。
 這些編譯後的native code何時被消除? 直到這個process  shutdown ,並由GC程序將process所reference到的memory都回收。

15) Pre-JITing
 使用ngen.exe:安裝時期先行編譯。

16) Verifier
 Verifier是JIT Compiler的一部份。
 Class Loader將Class load進來之後,verifier會進行檢查。
   ﹡metadata是不是well-formed
   ﹡IL Code是否Type Safe

17) Execution Support & Management
 GC
 Security management
 Code management(控制程式碼的執行)
 Exception management
 debug/profiling(提供debug/profile的API)
 marshaling management
 thread management


18) .NET與COM/Native Dll的互通性
 呼叫.NET元件
  ﹡Regasm.exe:將.NET Assembly註冊到系統的registry中。
  ﹡tlbexp:產生該Assembly的type library
  ﹡然後VB/VC就可以用呼叫一般COM元件的方式來使用這個.NET元件了。

 呼叫COM元件
  ﹡tlbimp.exe:為com 元件產生一個.NET PE的stub。(會產生一個dll檔)
  ﹡對這個.NET stub的呼叫都會被轉成對COM的呼叫。


19) Summary
 ﹡.NET和Java執行方式並不相同,CLR及JVM安裝在平台上的方式也不相同。安裝CLR後對整個作業系統影響較大。(ie.把OS的loader給換掉了)。
 ﹡.NET的程式利用metadata取代傳統的registry方式來描述自己。從而減少了dll hell的發生機會。
 ﹡所有.NET的程式經過managed compiler後都會變成IL,因此可達到跨語言的功能。但是變成XX.NET的語言都要符合CTS才行。
 ﹡CLS的標準只有部份被ECMA接受。
 ﹡所有.NET程式語言都使用相同一組library,所以只要學習一種.NET語言,其它語言都相當容易上手。
 ﹡在windows平台上無論是易用性及效能.NET都有出色的表現。移植到其它OS上表現能否一樣出色則尚待觀察。



---------------------------------------------------------
.NET程式的啟動與載入
.NET PE檔如何將控制權交給.NET CLR?
在進入Main()之前,.NET CLR做了哪些事?
.NET組件(assembly)與模組(module)是如何被載入記憶體的?
何謂類別載入器(class loader)?
JIT編譯器的運作原理為何?
本文章以一個實際的例子,幫助讀者理解.NET執行引擎(execution engine)內部的運作,在閱讀完本文章之後,這一切的困惑都將消失。



範例程式

本範例需要三個原始碼,分別是Main.cs、A.cs、BC.cs。下面是BC.cs的原始碼(包含兩個類別):

CODE:
[Copy to clipboard]
// BC.cs
public class ClassB {
    public static string GetString() {
        return "Class B";
    }
}
public class ClassC {
    public static string GetString() {
        return "Class C";
    }
}
下面是A.cs的原始碼:

CODE:
[Copy to clipboard]
// A.cs
public class ClassA {
    public static string GetString() {
        return "Class A";
    }
}
下面是Main.cs的原始碼:

CODE:
[Copy to clipboard]
// Main.cs
using System;
public class MainClass {
  public static void Main(string[] args) {
    for (int i=0; i< args.Length; i++) {
      switch (args[i]) {
        case "A" :
          ShowA(); break;
        case "B" :
          ShowB(); break;
        case "C" :
          ShowC(); break;
      }
    }
  }
  private static void ShowA() {
    Console.WriteLine(ClassA.GetString());
  }
  private static void ShowB() {
    Console.WriteLine(ClassB.GetString());
  }
  private static void ShowC() {
    Console.WriteLine(ClassC.GetString());
  }
}
我們首先將BC.cs編譯成一個模組(module),編譯完畢之後,可以得到一個名為BC.netmodule的模組檔案,其內部的格式也是.NET PE。編譯方式如下:

CODE:
[Copy to clipboard]
csc /t:module BC.cs
再將A.cs編譯成一個DLL組件,同時將BC.netmodule加入此組件。編譯完畢之後,可以得到一個多模組(multi-module),也是多檔案(multi-file)的組件,名為A.dll。作法如下:

CODE:
[Copy to clipboard]
csc /t:library /addmodule:BC.netmodule A.cs
最後,將Main.cs編譯成一個EXE組件。編譯完畢之後,可以得到一個名為Main.exe的組件。編譯方式如下:

CODE:
[Copy to clipboard]
csc /r:A.dll Main.cs
這些組件與模組的關係如圖1所示:
點擊查看全圖



進入Main()之前
執行Main.exe時,.NET CLR啟動的方式如下:
1. Windows所提供的PE Loader將Main.exe載入記憶體
2. Windows所提供的PE Loader將MsCorEE.dll載入記憶體(MsCorEE.dll位於C:\WINDOWS\System32或C:\WINNT\System32)
3. 程式跳到MsCorEE.dll內的 _CorExeMain()
4. _CorExeMain()會載入「適當版本的」.NET CLR。如果你的.NET是1.0.3705版,則.NET CLR位於C:\WINDOWS\Microsoft.NET\Framework\v1.0.3705或者C:\WINNT\Microsoft.NET\Framework\v1.0.3705
5. 程式跳到.NET CLR,進行一些初始化工作(initialization)
6. 載入assembly「MsCorLib」,載入module「MsCorLib.dll」,載入MsCorLib內的某些class
7. 產生主執行緒(main thread)
8. 載入「Main」組件,載入「Main.exe」模組,載入「MainClass」類別
9. 讓主執行緒開始執行MainClass.Main()


上述的1~3點,也就是在一開始載入Main.exe與MsCorEE.dll,並跳到_CorExeMain()的這部分,會因為Windows作業系統版本的不同,而有所差異。Windows XP與Windows Server 2003的loader因應.NET做了修改,更能符合 managed PE的需求。而Windows 2000/me/98的loader則未針對.NET做出修改。下面分別解釋它們的作法。

如果作業系統是Windows XP,當Windows XP的loader將Main.exe載入之後,會檢查PE header的data directory table (請參考圖 2)。如果COM_Header (亦稱為CLR_Header)內的值不為0,就表示是.NET PE,loader會立刻載入 MsCorEE.dll,並直接執行MsCorEE.dll內的_CorExeMain()。

如果作業系統是Windows 2000,當Windows 2000的loader將ain.exe載入之後,會檢查PE header的data directory table (請參考圖 2),將Import_Table所記錄的檔案都載入記憶體,以本例來說,就是MsCorEE.dll。接著找出PE header內所記錄的程式進入點(請參考圖 3),並執行此處的程式,這是x86機器碼,由編譯器自動產生,只有一道指令(6 bytes),為「FF 25 00 20 40 00」,翻譯成 x86組合語言就是「JMP DWORD PTR [402000]」,其中 0x00400000 是 Main.exe 的 image base,而0x2000是import address table的RVA(此處記錄著_CorExeMain() 的記憶體位址),所以執行「JMP DWORD PTR[402000]」的結果會跳到MsCorEE.dll的_CorExeMain()。

目前遊戲光碟所使用的防盜技術多達10數種,其中以SafeDisc、SecuRom、StarForce與實體壞軌保護等方式較為常見,下面就為用戶說明這幾種防拷方式的特色。

綜觀1~3點的作法,可以和Java作一個比較。Java執行方式如下所示:

java Hello

點擊查看全圖

點擊查看全圖



Java的作法是先執行VM(由java.exe進入),再請VM去執行Java bytecode。.NET的作法是,先執行.NET PE,立刻將控制權轉給.NET CLR,再由.NET CLR來執行.NET PE。.NET的作法固然使用上比Java方便,但其實.NET需要OS的loader配合,而Java不需要。

上述第4點提及_CorExeMain()會載入「適當版本的」.NET CLR。其實MsCorEE.dll 不是CLR,只是一個填隙程式(shim),負責搭起.NET PE和.NETCLR之間橋樑。MsCorEE會匯集足夠的資料,然後據以判斷要載入Workstation版(MsCorWks.dll)或者Server版(MsCorSvr.dll)的.NET CLR。以本例來說,被載入的是Workstation版的MsCorWks.dll。在載入MsCorWks.dll之後,還會陸續載入fusion.dll、MsCorSn.dll、MsCorJIT.dll等DLL檔。

事實上java.exe的角色和MsCorEE.dll的角色一樣,負責喚起適當版本的JVM。如果你安裝的是1.4.x的J2SE SDK而非1.4.x的JRE,你的JDK內會同時具備client和server兩個JVM,分別在JDK目錄下的jre\bin\client\jvm.dll與jre\bin\server\jvm.dll。第5點提到,程式跳到.NET CLR,進行一些初始化工作(initialization)。這些初始化的動作包括了:

* 準備一塊記憶體,以為managed heap之用。
* 準備好一個thread pool,以便CLR以及.NET程式庫稍後使用。
* 準備好一個application domain (簡稱為AppDomain)。


AppDomain是一個很複雜的主題,在此筆者只簡略地說明。基本上,AppDomain可以被視為sub-process,也就是對process所切割出來的小單位。AppDomain用來隔離不同的應用,任何被載入process的assembly,都歸屬於某個AppDomain 的管轄。一個process內可以有多個AppDomain,第一個建立的AppDomain是由.NET CLR自動建立的,稱為default AppDomain。default AppDomain剛開始時被命名為「DefaultDomain」,稍後會被更名。

第6點,載入「MsCorLib」組件。對於.NET來說,MsCorLib一定是第一個被載入的組件。MsCorLib是很特殊的組件,從某種角度來說,它可被視為是.NET CLR的一部份。MsCorLib只能屬於default AppDomain,不能屬於其他的AppDomain,因為它一定是被process內所有AppDomain共用的。

接著要載入「MsCorLib.dll」模組。對於MsCorLib這種單模組(single-module)的組件來說,雖然模組和組件是同一個檔案,但是邏輯上還是有所區隔。所以載入「MsCorLib」組件之後,還是需要載入「MsCorLib.dll」模組。接著要請class loader來載入MsCorLib內相關的class。利用工具觀察,此時載入的class依序如下:


System.Object
System.ICloneable
System.Collections.IEnumerable
…為節省篇幅,故略去中間一部份。
System.AppDomain
System.LoaderOptimization
System.Runtime.Remoting.Proxies.__TransparentProxy

       
       

請注意,此時並未載入MsCorLib內全部的class,只有載入目前需要的class。第7點,產生主執行緒(main thread),也因此觸發了對某些class的需求,於是又載入下列的這些 class:

                       
System.Threading.Monitor
System.IAppDomainSetup
System.AppDomainSetup
System.Char
System.Runtime.InteropServices.RuntimeEnvironment
System.RuntimeFieldHandle
System.Runtime.CompilerServices.RuntimeHelpers
$$struct0x6000136-1
System.Environment

               
               


第8點,載入「Main」組件,載入「Main.exe」模組,載入「MainClass」類別。請注意:「Main」組件被載入到」DefaultDomain」,「DefaultDomain」也隨即被改名為「Main」。(Default AppDomain在載入主程式的組件之後,會自動以組件名稱為AppDomain的名稱。)第9點,讓主執行緒真正進入程式,開始執行MainClass.Main()



進入Main()之後

class loader的作用是:將TypeDef相關的metadata從PE檔中讀進來,建立一個內部的資料結構(CORINFO_CLASS_STRUCT),此資料結構內有一個Non-Virtual Method Table和一個Virtual Method Table,紀錄著此class的每個method記憶體位址。一開始,method的記憶體都指向JIT編譯器。這造成一種現象:任何method第一次被執行時都會跳到JIT編譯器。JIT編譯器會進行下面的動作:

到metadata中查出此method的IL位址,將此method的IL編譯成x86的機器碼(Machine Code)將CORINFO_CLASS_STRUCT內的Method Table中此method的位址指向此機器碼的位址,如此一來,當下次再次執行相同的method時,就不會再通過JIT編譯器了。開始執行此x86機器碼。當程式開始執行MainClass.Main(),由於是第一次執行,所以先會通過JIT編譯器再執行。


實驗一

如果我們在執行Main.exe時,未指定任何命令列參數(common line argument),那麼,Main()就不會進入for迴圈,程式直接結束。整個執行過程中,A.dll與BC.netmodule都不會被載入到記憶體。


實驗二

如果我們在執行Main.exe時,指定一個命令列參數「A」,這會使得,Main() 進入for迴圈,並呼叫ShowA()。由於ShowA()尚未被呼叫過,所以會先進行JIT編譯。

JIT編譯時,有可能會觸發class loader。當Main()被JIT編譯時,由於Main()的IL完全不涉及其他class,所以不會觸發class loader,但是ShowA()就不同於Main()了,ShowA()的定義牽涉到Console和ClassA,這兩個class都尚未被載入記憶體 (也就是說它們都尚未具備CORINFO_CLASS_STRUCT資料結構),所以JIT編譯器會請求class loader的協助,將此二class載入之後,JIT編譯方能繼續。class loader先載入ClassA,再載入Console (此乃依據IL中兩者出現的前後次序,ClassA出現在前,Console出現在後)。

現ClassA所處的模組(也就是A.dll)並未被載入,於是請求module loader的協助;module loader試圖載入A.dll時,發現A.dll所處的組件(也就是A)並未被載入,於是請求assembly loader的協助;於是assembly loader載入「A」組件;module loader載入「A.dll」模組(注意:「BC.netmodule」並不會被載入),然後class loader就可以將ClassA載入記憶體。

class loader不一定會觸發module loader。當class loader試圖載入Console時,發現Console所處的module(也就是MsCorLib.dll)已經被載入,於是class loader逕自將ClassA載入記憶體,不需要assembly/module loader的協助。


實驗三

如果我們在執行Main.exe時,指定一個命令列參數「B」,這會使得,Main()進入for迴圈,並呼叫ShowB()。由於ShowB()尚未被呼叫過,所以會先進行JIT編譯;由於ClassB尚未被載入,所以JIT會請求class loader協助;由於ClassB所處的模組(也就是BC.netmodule)尚未被載入,所以class loader會請求module loader的協助;由於BC.netmodule所處的組件(也就是A)尚未被載入,所以module loader會請求assembly loader的協助。

於是,assembly loader將A載入記憶體,且由於.dll是prime module,所以必須緊接著組件之後被載入(儘管不需要用到ClassA),然後,BC.netmodule才被載入。class loader終於可以載入ClassB。

觀念整理

關於這三個實驗,目的在於讓讀者瞭解下面幾點:
* JIT編譯以method為單位,只有被呼叫到的method才會被編譯。
* JIT編譯器可能會觸發class loader。
* class loader可能會觸發module loader。
* module loader可能會觸發assembly loader。


[jocosn 在 2005-4-16 04:46 PM 作了最後編輯]
發表人: jocosn    時間: 2005-4-19 11:15 AM

Visual Basic 2005 中的程式語言加強功能
http://www.microsoft.com/taiwan/ ... ageEnhancements.htm

Visual C# .NET 2003 語言變更
http://www.microsoft.com/taiwan/ ... LanguageChanges.htm

C# 程式語言的未來功能
http://www.microsoft.com/taiwan/ ... eFutureFeatures.htm

Visual C# Whidbey 搶先預覽
http://www.microsoft.com/taiwan/ ... _csharp_preview.htm

Linux 上使用 .NET 計畫介紹
http://taiwan.cnet.com/enterprise/topic/0,2000062938,20090928,00.htm

[jocosn 在 2005-4-20 01:23 AM 作了最後編輯]
發表人: alexust    時間: 2005-4-21 01:59 AM

a free c sharp and vb.net ide

http://www.icsharpcode.net/OpenSource/SD/Default.aspx

develop (short for SharpDevelop) is a free IDE for C# and VB.NET projects on Microsoft's .NET platform. It is open-source (GPL), and you can download both sourcecode and executables from this site. In addition, you can find the latest information and changes on #develop, as well as get in touch with the team in the forum.

free vc complier toolkit

http://msdn.microsoft.com/visualc/vctoolkit2003/

如果無錢買visual studio, 就要他們吧!!!
發表人: jocosn    時間: 2005-5-30 08:04 AM

API Changes between versions of the .NET Framework
http://www.gotdotnet.com/team/upgrade/apiChanges.aspx




歡迎光臨 TWed2k (http://twed2k.org/) Powered by Discuz! 4.1.0