Udostępnij przez


.NET Native i kompilacja

Aplikacje klasyczne systemu Windows przeznaczone dla platformy .NET Framework są pisane w określonym języku programowania i kompilowane w języku pośrednim (IL). W czasie wykonywania kompilator JIT (Just-In-Time) jest odpowiedzialny za kompilowanie IL na kod natywny dla lokalnej maszyny tuż przed wykonaniem metody po raz pierwszy. Z kolei łańcuch narzędzi .NET Native konwertuje kod źródłowy na kod natywny w czasie kompilacji. W tym artykule porównano platformę .NET Native z innymi technologiami kompilacji dostępnymi dla aplikacji .NET Framework, a także praktycznym omówieniem sposobu tworzenia kodu natywnego przez platformę .NET Native, który może pomóc zrozumieć, dlaczego wyjątki występujące w kodzie skompilowanym za pomocą platformy .NET Native nie występują w kodzie skompilowanym JIT.

Generowanie natywnych plików binarnych

Aplikacja przeznaczona dla platformy .NET Framework, która nie jest kompilowana przy użyciu łańcucha narzędzi .NET Native, składa się z zestawu aplikacji, który obejmuje następujące elementy:

  • Metadane opisujące zestaw, jego zależności, typy, które zawiera, i ich składowe. Metadane są używane do odbicia i ograniczonego późno dostępu, a w niektórych przypadkach również przez kompilator i narzędzia kompilacji.

  • Kod implementacji. Składa się z kodów operacji języka pośredniego (IL). W czasie wykonywania kompilator just in time (JIT) tłumaczy go na natywny kod dla platformy docelowej.

Oprócz głównego zestawu aplikacji aplikacja wymaga obecności następujących elementów:

  • Wszelkie dodatkowe biblioteki klas lub biblioteki innych firm, które są wymagane przez aplikację. Zestawy te zawierają podobnie metadane opisujące zestaw, jego typy i ich składowe, a także IL, które implementują wszystkie elementy członkowskie typu.

  • Biblioteka klas programu .NET Framework. Jest to kolekcja zestawów zainstalowanych w systemie lokalnym z instalacją programu .NET Framework. Zestawy zawarte w bibliotece klas programu .NET Framework zawierają kompletny zestaw metadanych i kodu implementacji.

  • Środowisko uruchomieniowe języka wspólnego. Jest to kolekcja bibliotek dynamicznych, które wykonują takie usługi jak ładowanie zestawów, zarządzanie pamięcią i zbieranie śmieci, obsługa wyjątków, kompilacja Just-In-Time, komunikacja zdalna i interoperacyjność. Podobnie jak biblioteka klas, środowisko uruchomieniowe jest instalowane w systemie lokalnym w ramach instalacji programu .NET Framework.

Należy pamiętać, że całe środowisko uruchomieniowe języka wspólnego, a także metadane i IL dla wszystkich typów zestawów specyficznych dla aplikacji, zestawów innych firm i zestawów systemowych muszą być obecne, aby aplikacja mogła pomyślnie wykonać.

Kompilacja just in time

Dane wejściowe dla łańcucha narzędzi platformy .NET Native to aplikacja platformy UWP utworzona przez kompilator języka C# lub Visual Basic. Innymi słowy, łańcuch narzędzi platformy .NET Native rozpoczyna wykonywanie po zakończeniu kompilacji aplikacji platformy UWP przez kompilator języka.

Wskazówka

Ponieważ dane wejściowe do .NET Native to IL i metadane zapisywane w zarządzanych bibliotekach, nadal można wykonywać niestandardowe generowanie kodu lub inne operacje niestandardowe przy użyciu zdarzeń przed kompilacją lub po kompilacji, albo przez zmodyfikowanie pliku projektu MSBuild.

Jednak kategorie narzędzi, które modyfikują IL, a tym samym uniemożliwiają narzędziom .NET analizowanie IL aplikacji, nie są obsługiwane. Zaciemniacze są najbardziej godnymi uwagi narzędziami tego typu.

W trakcie konwertowania aplikacji z IL na kod natywny łańcuch narzędzi platformy .NET Native wykonuje operacje podobne do następujących:

  • W przypadku niektórych ścieżek kodu zastępuje kod, który zależy od mechanizmu odbijania i metadanych, na statyczny kod natywny. Jeśli na przykład typ wartości nie zastępuje metody ValueType.Equals, domyślny test równości używa refleksji do pobrania obiektów FieldInfo reprezentujących pola tego typu wartości, a następnie porównuje wartości pól dwóch wystąpień. Podczas kompilowania do kodu natywnego łańcuch narzędzi .NET Native zastępuje kod odbicia i metadane statycznym porównaniem wartości pól.

  • Jeśli to możliwe, próbuje wyeliminować wszystkie metadane.

  • Zawiera on w końcowych zestawach aplikacji tylko kod implementacji, który jest faktycznie wywoływany przez aplikację. Ma to szczególnie wpływ na kod w bibliotekach innych firm i w bibliotece klas programu .NET Framework. W związku z tym aplikacja nie zależy już od bibliotek innych firm lub pełnej biblioteki klas programu .NET Framework; Zamiast tego kod w bibliotekach klas innych firm i .NET Framework jest teraz lokalny dla aplikacji.

  • Zastępuje pełne środowisko CLR zrefaktoryzowanym środowiskiem uruchomieniowym, które zawiera przede wszystkim moduł garbage collector. Refaktoryzowane środowisko uruchomieniowe znajduje się w bibliotece o nazwie mrt100_app.dll, która jest lokalna dla aplikacji i ma tylko kilkaset kilobajtów rozmiaru. Jest to możliwe, ponieważ łączenie statyczne eliminuje potrzebę wielu usług wykonywanych przez środowisko uruchomieniowe języka wspólnego.

    Uwaga / Notatka

    Platforma .NET Native używa tego samego kolektora śmieci, co standardowe wspólne środowisko uruchomieniowe. W macierzystym module odśmiecającym pamięci platformy .NET funkcja odzyskiwania pamięci w tle jest domyślnie włączona. Aby uzyskać więcej informacji na temat odśmiecania, zobacz Podstawy odśmiecania.

Ważne

Platforma .NET Native kompiluje całą aplikację do aplikacji natywnej. Nie umożliwia skompilowania zestawu, który zawiera bibliotekę klas, do kodu natywnego, aby można go było wywołać niezależnie od kodu zarządzanego.

Aplikacja wynikowa, utworzona przez łańcuch narzędzi .NET Native, jest zapisywana w katalogu o nazwie ilc.out w katalogu Debug lub Release w katalogu projektu. Składa się z następujących plików:

  • <appName>.exeprogramu stub, który po prostu przenosi kontrolę do specjalnego eksportu Main w <appName>.dll.

  • <appName>.dll, biblioteka linków dynamicznych systemu Windows zawierająca cały kod aplikacji, a także kod z biblioteki klas programu .NET Framework i wszystkich bibliotek innych firm, na których istnieje zależność. Zawiera również kod pomocy technicznej, taki jak kod niezbędny do współdziałania z systemem Windows i serializowanie obiektów w aplikacji.

  • mrt100_app.dll, zrefaktoryzowane środowisko uruchomieniowe, które zapewnia usługi wykonawcze, takie jak odzyskiwanie pamięci.

Wszystkie zależności są przechwytywane przez manifest APPX aplikacji. Oprócz pliku exe, dll i mrt100_app.dllaplikacji, które są powiązane bezpośrednio z pakietem appx, obejmuje to dwa kolejne pliki:

  • msvcr140_app.dll, biblioteka środowiska uruchomieniowego języka C (CRT) używana przez mrt100_app.dll. Jest ono dołączane poprzez odwołanie do frameworka w pakiecie.

  • mrt100.dll. Ta biblioteka zawiera funkcje, które mogą poprawić wydajność mrt100_app.dll, chociaż jej brak nie uniemożliwia mrt100_app.dll działania. Jest on ładowany z katalogu system32 na komputerze lokalnym, jeśli jest obecny.

Ponieważ łańcuch narzędzi platformy .NET Native łączy kod implementacji z aplikacją tylko wtedy, gdy aplikacja rzeczywiście wywołuje ten kod, metadane lub kod implementacji wymagany w następujących scenariuszach mogą nie być dołączone do aplikacji:

  • Odbicie.

  • Wywołanie dynamiczne lub opóźnione.

  • Serializacja i deserializacja.

  • Interoperacyjność COM.

Jeśli wymagane metadane lub kod implementacji są nieobecne w czasie wykonywania, środowisko uruchomieniowe platformy .NET Native zgłasza wyjątek. Można zapobiec tym wyjątkom i upewnić się, że łańcuch narzędzi .NET Native zawiera wymagane metadane i kod implementacji, używając pliku dyrektyw środowiska uruchomieniowego, pliku XML, który wyznacza elementy programu, których metadane lub kod implementacji muszą być dostępne w czasie wykonywania i przypisuje do nich zasady środowiska uruchomieniowego. Poniżej znajduje się domyślny plik dyrektyw środowiska uruchomieniowego dodany do projektu platformy UWP skompilowanego przez łańcuch narzędzi .NET Native:

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

To umożliwia wszystkie typy oraz wszystkich ich członków we wszystkich zestawach w pakiecie aplikacji do refleksji i dynamicznego wywoływania. Jednak nie umożliwia refleksji ani dynamicznej aktywacji typów w bibliotekach klas programu .NET Framework. W wielu przypadkach jest to odpowiednie.

Zobacz także