.NET 原生和編譯.NET Native and Compilation

以 .NET Framework 為目標的 Windows 8.1 應用程式及 Windows 桌面應用程式,會以特定的程式設計語言撰寫,並會編譯成中繼語言 (IL)。Windows 8.1 applications and Windows Desktop applications that target the.NET Framework are written in a particular programming language and compiled into intermediate language (IL). 在執行階段,Just-In-Time (JIT) 編譯器在第一次執行方法之前,才會負責編譯 IL 為本機電腦的原生程式碼。At runtime, a just-in-time (JIT) compiler is responsible for compiling the IL into native code for the local machine just before a method is executed for the first time. 相較之下,.NET 原生工具鏈會在編譯時期轉換原始碼為原生程式碼。In contrast, the .NET Native tool chain converts source code to native code at compile time. 本主題比較 .NET 原生與其他適用於 .NET Framework 應用程式的編譯技術,並提供 .NET 原生如何產生原生程式碼的實用概觀,可協助您了解為什麼在以 .NET 原生編譯的程式碼中發生的例外狀況不會發生在 JIT 編譯程式碼中。This topic compares .NET Native with other compilation technologies available for .NET Framework apps, and also provides a practical overview of how .NET Native produces native code that can help you understand why exceptions that occur in code compiled with .NET Native do not occur in JIT-compiled code.

.NET 原生:產生原生二進位檔.NET Native: Generating native binaries

目標為 .NET Framework 且不使用 .NET 原生工具鏈編譯的應用程式,可由您的應用程式組件組成,其中包含下列項目:An application that targets the .NET Framework and that is not compiled by using the .NET Native tool chain consists of your application assembly, which includes the following:

  • 描述組件、其相依性、包含的類型和其成員的中繼資料Metadata that describes the assembly, its dependencies, the types it contains, and their members. 中繼資料用於反映和晚期繫結存取,以及在某些情況下也由編譯器及建置工具所使用。The metadata is used for reflection and late-bound access, and in some cases by compiler and build tools as well.

  • 實作程式碼。Implementation code. 這包含中繼語言 (IL) Opcode。This consists of intermediate language (IL) opcodes. 在執行階段,Just-In-Time (JIT) 編譯器將其轉譯成目標平台的原生程式碼。At runtime, the just-in-time (JIT) compiler translates it into native code for the target platform.

除了主要應用程式組件,應用程式會要求下列項目必須存在:In addition to your main application assembly, an app requires that the following be present:

  • 任何您應用程式所需的其他類別庫或協力廠商組件。Any additional class libraries or third-party assemblies that are required by your app. 這些組件同樣包含描述組件、類型及成員的中繼資料,以及實作所有類型成員的 IL。These assemblies similarly include metadata that describes the assembly, its types, and their members, as well as the IL that implements all type members.

  • .NET Framework 類別庫The .NET Framework Class Library. 這是在安裝 .NET Framework 時安裝在本機系統的組件集合。This is a collection of assemblies that is installed on the local system with the .NET Framework installation. 包含在 .NET Framework 類別庫中的組件含有一組完整的中繼資料和實作的程式碼。The assemblies included in the .NET Framework Class Library include a complete set of metadata and implementation code.

  • Common Language Runtime。The common language runtime. 這是做為組件載入的動態連結程式庫集合,會執行這類服務如:記憶體管理和記憶體回收、例外狀況處理、Just-In-Time 編譯、遠端處理和 Interop。This is a collection of dynamic link libraries that perform such services as assembly loading, memory management and garbage collection, exception handling, just-in-time compilation, remoting, and interop. 就像類別庫,執行階段會安裝在本機系統上,做為安裝 .NET Framework 的一部分。Like the class library, the runtime is installed on the local system as part of the .NET Framework installation.

請注意必須有整個 Common Language Runtime 以及應用程式特有的組件、協力廠商組件和系統組件中所有類型的中繼資料和 IL,才能讓應用程式順利執行。Note that the entire common language runtime, as well as metadata and IL for all types in application-specific assemblies, third-party assemblies, and system assemblies must be present for the app to execute successfully.

.NET 原生和 Just-In-Time 編譯.NET Native and just-in-time compilation

.NET 原生工具鏈的輸入,是 C# 或 Visual Basic 編譯器所建置的 Windows 市集應用程式。The input for the .NET Native tool chain is the Windows store app built by the C# or Visual Basic compiler. 換句話說,當語言編譯器完成 Windows 市集應用程式的編譯時,.NET Native 工具鏈就會開始執行。In other words, the .NET Native tool chain begins execution when the language compiler has finished compilation of a Windows Store app.

提示

因為 .NET Native 的輸入是寫入至 Managed 組件中的 IL 和中繼資料,您仍然可以使用建置前或建置後事件,或修改 MSBuild 專案檔,來執行自訂程式碼產生或其他自訂作業。Because the input to .NET Native is the IL and metadata written to managed assemblies, you can still perform custom code generation or other custom operations by using pre-build or post-build events or by modifying the MSBuild project file.

不過,不支援會修改 IL,並藉此防止 .NET 工具鏈分析應用程式 IL 的類別。However, categories of tools that modify IL and thereby prevent the .NET tool chain from analyzing an app's IL are not supported. 模糊化是這種類型最值得注意的工具。Obfuscators are the most notable tools of this type.

在應用程式從 IL 轉換成原生程式碼的過程中,.NET Native 工具鏈會執行如下所示的作業:In the course of converting an app from IL to native code, the .NET Native tool chain performs operations like the following:

  • 對於某些程式碼路徑,它會取代依賴反映和中繼資料的程式碼為靜態機器碼。For certain code paths, it replaces code that relies on reflection and metadata with static native code. 例如,如果實值類型不覆寫 ValueType.Equals 方法,則測試是否相等的預設測試會使用反映來擷取 FieldInfo 物件,此物件表示值類型的欄位,然後會比較兩個執行個體的欄位值。For example, if a value type does not override the ValueType.Equals method, the default test for equality uses reflection to retrieve FieldInfo objects that represent the value type's fields, then compares the field values of two instances. 當編譯為機器碼時,.NET Native 工具鏈會取代反映程式碼和中繼資料為欄位值的靜態比較。When compiling to native code, the .NET Native tool chain replaces the reflection code and metadata with a static comparison of the field values.

  • 如果可行的話,它會嘗試排除所有中繼資料。Where possible, it attempts to eliminate all metadata.

  • 在最終的應用程式組件中只包含應用程式所實際叫用的實作程式碼。It includes in the final app assemblies only the implementation code that is actually invoked by the app. 這尤其會影響協力廠商程式庫和 .NET Framework 類別庫中的程式碼。This particularly affects code in third-party libraries and in the .NET Framework Class Library. 如此一來,應用程式不再依賴協力廠商程式庫或完整 .NET Framework 類別庫;相反地,現在協力廠商和 .NET Framework 類別庫中的程式碼對於應用程式而言是本機的。As a result, an application no longer depends on either third-party libraries or the full .NET Framework Class Library; instead, code in third-party and .NET Framework class libraries is now local to the app.

  • 它會取代完整的 CLR 為重構的執行階段,主要包含記憶體回收行程。It replaces the full CLR with a refactored runtime that primarily contains the garbage collector. 重構的執行階段會在名為 mrt100_app.dll 的程式庫中找到,對於應用程式而言是本機的,而且也只有數百 KB 大小。The refactored runtime is found in a library named mrt100_app.dll that is local to the app and is only a few hundred kilobytes in size. 這可能是因為靜態連結不需要許多由 Common Language Runtime 所執行的服務。This is possible because static linking eliminates the need for many of the services performed by the common language runtime.

    注意

    .NET 原生使用相同的記憶體回收行程,如同標準的 Common Language Runtime 。.NET Native uses the same garbage collector as the standard common language runtime. 在 .NET 原生記憶體回收行程中,預設會啟用背景記憶體回收。In the .NET Native garbage collector, background garbage collection is enabled by default. 如需記憶體回收的詳細資訊,請參閱記憶體回收的基本概念For more information about garbage collection, see Fundamentals of Garbage Collection.

重要

.NET 原生會編譯整個應用程式為原生應用程式。.NET Native compiles an entire application to a native application. 它不允許您編譯包含類別程式庫的單一組件為原生程式碼,如此一來才可單獨從 Managed 程式碼中呼叫它。It does not allow you to compile a single assembly that contains a class library to native code so that it can be called independently from managed code.

由 .NET 原生工具鏈所產生的應用程式會寫入名為 ilc.out 的目錄,位於您專案目錄的偵錯或發行目錄中。The resulting app that is produced by the .NET Native tool chain is written to a directory named ilc.out in the Debug or Release directory of your project directory. 它包含下列檔案:It consists of the following files:

  • <appName>.exe 是存根可執行檔,只會將控制項傳輸至 Main .dll 中的特殊匯出。 <appName><appName>.exe, a stub executable that simply transfers control to a special Main export in <appName>.dll.

  • <appName>.dll,這是一種 Windows 動態連結程式庫,其中包含您所有的應用程式程式碼,以及來自 .NET Framework 類別庫和任何相依于之協力廠商程式庫的程式碼。<appName>.dll, a Windows dynamic link library that contains all your application code, as well as code from the .NET Framework Class Library and any third-party libraries that you have a dependency on. 它也包含支援程式碼,例如應用程式中與 Windows 交互操作及序列化物件所必需的程式碼。It also contains support code, such as the code necessary to interoperate with Windows and to serialize objects in your app.

  • mrt100_app.dll 為重構的執行階段,會提供執行階段服務,例如記憶體回收。mrt100_app.dll, a refactored runtime that provides runtime services such as garbage collection.

應用程式的 APPX 資訊清單會擷取所有相依性。All dependencies are captured by the app's APPX manifest. 除了直接組合在 appx 封裝中的應用程式 exe、dll 和 mrt100_app.dll 之外,這還包含另外兩個檔案:In addition to the application exe, dll, and mrt100_app.dll, which are bundled directly in the appx package, this includes two more files:

  • msvcr140_app.dll,其為 mrt100_app.dll 所使用的 C 執行階段 (CRT) 程式庫。msvcr140_app.dll, the C run-time (CRT) library used by mrt100_app.dll. 它會包含在封裝中的 Framework 參考。It is included by a framework reference in the package.

  • mrt100.dll。mrt100.dll. 此程式庫包含可改善 mrt100_app.dll 效能的函式,儘管沒有它也不會造成 mrt100_app.dll 無法正常運作。This library includes functions that can improve the performance of mrt100_app.dll, although its absence does not prevent mrt100_app.dll from functioning. 如果有的話,會從本機電腦的 System32 目錄載入它。It is loaded from the system32 directory on the local machine, if it is present.

因為 .NET Native 工具鏈只會在當它知道您的應用程式會實際叫用該程式碼時才會連結實作程式碼到應用程式中,所以下列案例所需的中繼資料或實作程式碼可能未必包含於您的應用程式中:Because the .NET Native tool chain links implementation code into your app only if it knows that your app actually invokes that code, either the metadata or the implementation code required in the following scenarios may not be included with your app:

  • 反映。Reflection.

  • 動態或晚期繫結引動過程。Dynamic or late-bound invocation.

  • 序列化與還原序列化。Serialization and deserialization.

  • COM Interop。COM interop.

如果在執行階段沒有必要的中繼資料或實作程式碼,則 .NET Native 執行階段會擲回例外狀況。If the necessary metadata or implementation code is absent at runtime, the .NET Native runtime throws an exception. 您可以防止這些例外狀況發生,並確認 .NET Native 工具鏈中包含必要的中繼資料和實作程式碼,這可藉由使用執行階段指示詞檔案達成,此為指定程式項目的 XML 檔案,其中繼資料或實作程式碼必須是在執行階段可用的,且指派執行階段原則給程式項目。You can prevent these exceptions, and ensure that the .NET Native tool chain includes the required metadata and implementation code, by using a runtime directives file, an XML file that designates the program elements whose metadata or implementation code must be available at runtime and assigns a runtime policy to them. 以下是加入由 .NET 原生工具鏈所編譯的 Windows 市集專案之預設執行階段指示詞檔案:The following is the default runtime directives file that is added to a Windows Store project that is compiled by the .NET Native tool chain:

<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
  <Application>
    <Assembly Name="*Application*" Dynamic="Required All" />
  </Application>
</Directives>

這會在應用程式封裝中的所有組件裡啟用所有類型及其所有成員,供反映和動態引動過程之用。This enables all the types, as well as all their members, in all the assemblies in your app package for reflection and dynamic invocation. 不過,它不會啟用 .NET Framework 類別庫組件中類型的反映或動態啟動。However, it does not enable reflection or dynamic activation of types in .NET Framework Class Library assemblies. 在許多情況下,這樣已足夠。In many cases, this is adequate.

.NET 原生和 NGEN.NET Native and NGEN

原生映像產生器 (NGEN) 會將組件編譯成機器碼,並在本機電腦的原生映像快取中安裝它們。The (Native Image Generator (NGEN) compiles assemblies to native code and installs them in the native image cache on the local computer. 不過,儘管 NGEN 如同 .NET 原生會產生機器碼,仍有幾個不同於 .NET 原生的顯著區別:However, although NGEN, like .NET Native, produces native code, it differs from .NET Native in some significant ways:

  • 如果沒有原生映像能用於特定的方法,NGEN 會轉而使用 JIT 編譯的程式碼。If no native image is available for a particular method, NGEN falls back to JITing code. 這表示在 NGEN 需要轉而使用 JIT 編譯的情況下,原生映像必須繼續包含中繼資料和 IL。This means that native images must continue to include metadata and IL in the event that NGEN needs to fall back to JIT compilation. 相反地,.NET 原生只會產生原生映像,並不會轉而產生 JIT 編譯。In contrast, .NET Native produces only native images and does not fall back to JIT compilation. 如此一來,您只需保留一些反映、序列化和 Interop 案例所需的中繼資料。As a result, only metadata required for some reflection, serialization, and interop scenarios must be preserved.

  • NGEN 繼續依賴完整 Common Language Runtime 的服務,例如組件載入、遠端處理、Interop、記憶體管理、記憶體回收,若有需要的話,也依賴 JIT 編譯。NGEN continues to rely on the full common language runtime for services such as assembly loading, remoting, interop, memory management, garbage collection, and, if necessary, JIT compilation. 在 .NET 原生中,這些服務有許多都不必要 (JIT 編譯) 或會在建置階段解決,並且併入應用程式組件中。In .NET Native, many of these services are either unnecessary (JIT compilation) or are resolved at build-time and incorporated in the app assembly. 其中最重要的剩餘服務是記憶體回收,會包含在較小、重構的執行階段,名為 mrt100_app.dll。The remaining services, the most important of which is garbage collection, are included in a much smaller, refactored runtime named mrt100_app.dll.

  • NGEN 映像通常易於損壞。NGEN images tend to be fragile. 例如,修補檔案或相依性的變更通常要求使用它的組件也是由原生映像所產生的。For example, a patch or change to a dependency typically requires that the assemblies that use it also be re-NGENed. 特別在 .NET Framework 類別庫中的系統組件更是如此。This is particularly true of system assemblies in the .NET Framework Class Library. 相反地,.NET 原生允許獨立地服務彼此的應用程式。In contrast, .NET Native allows applications to be served independently of one another.

另請參閱See also