.NET Native a proces kompilace

Desktopové aplikace windows, které cílí na rozhraní .NET Framework, jsou napsány v konkrétním programovacím jazyce a kompilovány do zprostředkujícího jazyka (IL). Za běhu zodpovídá kompilátor JIT (just-in-Time) za kompilaci IL do nativního kódu místního počítače těsně před prvním spuštěním metody. Naproti tomu řetězec nástrojů .NET Native převádí zdrojový kód na nativní kód v době kompilace. Tento článek porovnává rozhraní .NET Native s dalšími kompilačními technologiemi dostupnými pro aplikace .NET Framework a také poskytuje praktický přehled o tom, jak .NET Native vytváří nativní kód, který vám pomůže pochopit, proč výjimky, ke kterým dochází v kódu zkompilovaném pomocí .NET Native, v kompilovaném kódu JIT nedochází.

Generování nativních binárních souborů

Aplikace, která cílí na rozhraní .NET Framework a která není kompilována pomocí řetězu nástrojů .NET Native, se skládá z sestavení aplikace, které zahrnuje následující:

  • Metadata, která popisuje sestavení, jeho závislosti, typy, které obsahuje, a jejich členy. Metadata se používají pro reflexi, pozdější přístup a v některých případech je využívají také kompilátor a nástroje sestavení.

  • Kód implementace. Skládá se z operačních kódů zprostředkujícího jazyka (IL). Kompilátor JIT (Just-in-Time) za běhu ho přeloží do nativního kódu pro cílovou platformu.

Kromě hlavního sestavení aplikace vyžaduje aplikace, aby byla k dispozici následující:

  • Všechny další knihovny tříd nebo sestavení třetích stran, které vaše aplikace vyžaduje. Tato sestavení podobně zahrnují metadata, která popisují sestavení, jeho typy a jejich členy, stejně jako IL, které implementuje všechny členy typu.

  • Knihovna tříd rozhraní .NET Framework. Jedná se o kolekci sestavení, která jsou nainstalována v místním systému s instalací rozhraní .NET Framework. Sestavení zahrnutá v knihovně tříd rozhraní .NET Framework zahrnují úplnou sadu metadat a kódu implementace.

  • Společné jazykové runtime. Jedná se o kolekci knihoven dynamického propojení, které provádějí služby, jako je načítání sestavení, správa paměti a uvolňování paměti, zpracování výjimek, kompilace za běhu, vzdálená komunikace a interoperabilita. Podobně jako knihovna tříd se modul runtime nainstaluje do místního systému jako součást instalace rozhraní .NET Framework.

Mějte na paměti, že ke spuštění aplikace musí být přítomná celá platforma CLR, stejně jako metadata a IL pro všechny typy v sestaveních specifických pro aplikaci, v sestaveních třetích stran a systémových sestaveních.

Just-in-time kompilace

Vstup pro řetěz nástrojů .NET Native je aplikace UPW vytvořená kompilátorem jazyka C# nebo Visual Basic. Jinými slovy, řetězec nástrojů .NET Native začne s prováděním, když kompilátor jazyka dokončil kompilaci aplikace pro UPW.

Návod

Jelikož vstupem do .NET Native je IL a metadata zapsaná do spravovaných sestavení, můžete i tak provádět vlastní generování kódu nebo jiné vlastní operace pomocí událostí před sestavením nebo po sestavení, nebo úpravou souboru projektu MSBuild.

Kategorie nástrojů, které upravují il a tím brání řetězu nástrojů .NET v analýze IL aplikace, se ale nepodporují. Obfuscátory jsou nejvýznamnějšími nástroji tohoto typu.

V průběhu převodu aplikace z IL na nativní kód provádí řetěz nástrojů .NET Native operace jako následující:

  • U určitých cest kódu nahrazuje kód, který spoléhá na reflexi a metadata statickým nativním kódem. Pokud například typ hodnoty nepřepíše metodu ValueType.Equals, použije výchozí test rovnosti reflexi k načtení FieldInfo objektů, které představují pole typu hodnoty, a pak porovná hodnoty polí dvou instancí. Při kompilaci do nativního kódu nahradí řetězec nástrojů .NET Native kód reflexe a metadata statickým porovnáním hodnot polí.

  • Pokud je to možné, pokusí se odstranit všechna metadata.

  • Zahrnuje do finálních sestavení aplikace pouze kód implementace, který je ve skutečnosti vyvolán aplikací. To se týká zejména kódu v knihovnách třetích stran a v knihovně tříd rozhraní .NET Framework. V důsledku toho už aplikace nezávisí na knihovnách třetích stran nebo na úplné knihovně tříd rozhraní .NET Framework; místo toho je kód v knihovnách tříd rozhraní .NET Framework třetích stran místní pro aplikaci.

  • Nahrazuje plný CLR refaktorovaným runtime, který primárně obsahuje garbage collector. Refaktorovaný modul runtime se nachází v knihovně s názvem mrt100_app.dll, která je místní pro aplikaci a je ve velikosti jen pár stovek kilobajtů. To je možné, protože statické propojení eliminuje potřebu mnoha služeb prováděných modulem CLR (Common Language Runtime).

    Poznámka:

    .NET Native používá stejný garbage collector jako standardní modul CLR (Common Language Runtime). V systému .NET Native uvolňování paměti je ve výchozím nastavení povolená uvolňování paměti na pozadí. Další informace o uvolňování paměti naleznete v tématu Základy uvolňování paměti.

Důležité

.NET Native zkompiluje celou aplikaci do nativní aplikace. Neumožňuje kompilovat jedno sestavení, které obsahuje knihovnu tříd do nativního kódu, aby bylo možné ji volat nezávisle na spravovaném kódu.

Výsledná aplikace vytvořená řetězem nástrojů .NET Native se zapíše do adresáře s názvem ilc.out v adresáři Debug nebo Release vašeho adresáře projektu. Skládá se z následujících souborů:

  • <appName>.exe, zástupný spustitelný soubor, který jednoduše přenese řízení na export Main ve speciálním <appName>.dll.

  • <appName>.dll, dynamická knihovna windows, která obsahuje veškerý kód aplikace, stejně jako kód z knihovny tříd rozhraní .NET Framework a všech knihoven třetích stran, na kterých jste závislí. Obsahuje také kód podpory, například kód nezbytný pro spolupráci s Windows a serializaci objektů ve vaší aplikaci.

  • mrt100_app.dll– refaktorovaný modul runtime, který poskytuje služby runtime, jako je uvolňování paměti.

Všechny závislosti jsou zachyceny manifestem APPX aplikace. Kromě souboru exe, knihovny DLL a mrt100_app.dll, které jsou spojeny přímo v balíčku appx, to zahrnuje dva další soubory:

  • msvcr140_app.dll, knihovna C run-time (CRT) používaná mrt100_app.dll. V balíčku je zahrnut odkaz na framework.

  • mrt100.dll. Tato knihovna obsahuje funkce, které mohou zlepšit výkon mrt100_app.dll, i když jeho absence nebrání mrt100_app.dll fungování. Je načten z adresáře system32 na místním počítači, pokud je k dispozici.

Vzhledem k tomu, že řetěz nástrojů .NET Native propojí kód implementace do vaší aplikace pouze v případě, že ví, že aplikace tento kód skutečně vyvolá, buď metadata nebo implementační kód vyžadovaný v následujících scénářích, nemusí být součástí vaší aplikace:

  • Odraz.

  • Dynamické nebo opožděné vyvolání

  • Serializace a deserializace.

  • Interoperabilita modelu COM

Pokud za běhu chybí potřebná metadata nebo implementační kód, modul runtime .NET Native vyvolá výjimku. Těmto výjimkám můžete zabránit a zajistit, aby řetězec nástrojů .NET Native obsahoval požadovaný kód metadat a implementace pomocí souboru direktiv modulu runtime , souboru XML, který určuje prvky programu, jejichž metadata nebo implementační kód musí být k dispozici za běhu, a přiřadí jim zásady modulu runtime. Následuje výchozí soubor direktiv modulu runtime, který je přidaný do projektu UPW kompilovaného řetězem nástrojů .NET Native:

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

Toto umožňuje všechny typy a jejich členy ve všech sestaveních v balíčku aplikace pro účely reflexe a dynamického vyvolání. Neumožňuje však reflexi ani dynamickou aktivaci typů v sestaveních knihovny tříd rozhraní .NET Framework. V mnoha případech je to adekvátní.

Viz také