Arquitetura do .NET
Quero mostrar nesse post, com base em algumas referências a arquitetura do .NET e suas partes.
Antes de falar das partes que constituem o .NET, seguem os benefícios da plataforma.
- Interoperabilidade com o código existente, através do .NET Standard.
- Suporte para várias linguagens, como C#, F#, e VB.NET.
- Runtime compartilhado por todas as linguagens do .NET.
- Integração entre as linguagens.
- Biblioteca de classes para construir diversos tipos de aplicações.
- Modelo de deploy simplificado.
- Fornece uma CLI extensa. (.NET Core/NET 5)
As partes constituintes do .NET
A plataforma .NET é formada pelos seguintes componentes:
- CLR
- CTS
- CLS
- BCL
- CIL
CLR — Common Lanaguage Runtime
A camada do runtime do .NET é comporto pelo Common Language Runtime ou apenas CLR (CoreCLR no .NET Core e .NET Core Libraries ou apenas CoreFX). A partir do NET 5, podemos chamar de .NET CLR.
O CoreCLR é um conjunto minimo de implementações ligadas a plataforma (Windows, iOS, Linux) e a arquitetura (x86, x64, ARM). Apenas os tipos que são ligados à implantação são incluídas no CoreCLR, mas são definidos como privados e não são acessíveis através do CoreCLR.
O .NET CLR é um tempo de execução de plataforma cruzada que também inclui suporte para Windows, MacOS e Linux. O CLR manipula a alocação e o gerenciamento de memória. O CLR também é uma máquina virtual que não só executa aplicativos, mas também gera e compila código usando um compilador JIT (just-in-time).
O CLR de modo geral executa o código e fornece serviços que facilitam o processo de desenvolvimento.
Os Compiladores e ferramentas expõem as funcionalidades do CLR e permitem que você grave um código que se beneficia desse ambiente de execução gerenciado. O código que você desenvolve com um compilador de linguagem que tem como alvo o tempo de execução é chamado de código gerenciado.
O código gerenciado beneficia-se de recursos como integração entre linguagens, tratamento de exceção entre linguagens, segurança aprimorada, controle de versão e implantação, um modelo simplificado para interação de componente e serviços de depuração e criação de perfil.
O CLR oferece os seguintes benefícios:
- Aprimoramentos no desempenho.
- A possibilidade de usar facilmente componentes desenvolvidos em outras linguagens.
- Tipos extensíveis fornecidos por uma biblioteca de classes.
- Recursos de linguagem como herança, interfaces e sobrecarga para programação orientada ao objeto.
- Suporte a threading explícito que permite a criação de aplicativos multithread, escalonáveis.
- Suporte ao tratamento de exceções estruturado.
- Suporte a atributos personalizados.
- Coleta de lixo.
- Uso de delegados em vez de ponteiros de função para maior segurança e segurança de tipos.
O CoreFX (.NET Core) é agnóstico de plataforma e inclui todos os tipos base do .NET Core. Esses tipos incluem a implementação pública dos tipos privados do CoreCLR. Juntos o CoreCLR e o CoreFX correspondem ao .NET Core Framework, e são usados juntos para rodar aplicações .NET Core.
Gerenciamento automático de memória
Um dos serviços oferecidos pela CLR, de extrema importância que gostaria de destacar é o GC (Garbage Collector).
O GC gerencia a alocação e a liberação de memória para aplicativos. Cada vez que seu código cria um novo objeto, o CLR aloca memória para o objeto a partir do heap gerenciado.
Para saber mais detalhes sobre como GC funciona, segue: Noções básicas da coleta de lixo
Versões da CLR
Assim como o .NET foi evoluindo com o tempo, o CLR também possui algumas versões, onde em cada uma delas foi ganhando melhorias.
Para mais detalhes sobre as versões acesse: .NET Framework & versões do sistema operacional Windows
CTS — Common Type System
O Common Type System (CTS) descreve todos os possíveis data types e todas as construções suportadas pelo runtime, especifica como eles podem interagir uns com os outros e os detalhes de como eles são representados no metadata do .NET. O CTS assegura que todo código gerenciado seja auto-descritivo. Os diversos compiladores de linguagem da Microsoft e de terceiros geram códigos gerenciados de acordo com o CTS.
Definições feitas pela CTS
- CTS Class
- CTS Interface
- CTS Structure Types
- CTS Enumeration
- CTS Delegate
- CTS Members
- CTS Data Types
CLS — Common Language Specification
O Common Language Specification (CLS) define um subconjunto de tipos comuns e construções que toda linguagem .NET pode suportar. Portanto, se você construir um tipo que expõe recursos CLS-compliant, você pode ter certeza que todas as linguagens .NET podem consumi-lo.
BCL — Base Class Libraries
E temos também a Base Class Libraries (BCLs), a BCL encapsula vários recursos como threads, file IO, renderização gráfica, interação com hardware e etc.
E além de bibliotecas para tarefas comuns, a BCL inclui tipos que dão suporte aos seguinte cenários de desenvolvimento:
- Aplicativos de console. Confira Compilação de aplicativos de console.
- Aplicativos GUI do Windows (Windows Forms). Confira Windows Forms.
- Aplicativos WPF (Windows Presentation Foundation). Confira Windows Presentation Foundation.
- Aplicativos ASP.NET. Confira Aplicativos Web com o ASP.NET.
- Serviços do Windows. Confira Introdução a aplicativos do Serviço Windows.
- Aplicativos orientados a serviço usando o WCF (Windows Communication Foundation). Confira Aplicativos orientados a serviço com WCF.
- Aplicativos habilitados para fluxo de trabalho usando o Windows Workflow Foundation (WF). Confira Windows Workflow Foundation.
CIL — Common Intermediate Language
A MSIL, CIL ou IL é uma linguagem que é independente de plataforma. Toda linguagem .NET é compilada para CIL antes de ser executada para código especifico da plataforma. Existem diferenças muito pequenas entre um código CIL compilado a partir do C#, F# e VB.NET, ou seja, independente da linguagem, a CIL gerada é praticamente a mesma. Ao compilar o código de qualquer linguagem .NET, como o C#, a DLL resultante irá conter código CIL.
Abaixo exemplo de uma saída IL:
JIT
A compilação da IL para plataforma especifica é feita através do compilador JIT (just-in-time) ou também chamado de jitter. O ambiente de execução do .NET utiliza um compilador JIT para cada CPU alvo. Por exemplo, se você construir uma aplicação mobile (iOS ou Android) o compilador JIT correspondente será otimizado para um ambiente low-memory, caso seja um servidor o JIT será otimizado para funcionar em high-memory. A compilação JIT ocorre no mesmo computador em que o código vai ser executado.
O JIT, além de compilar a IL para a plataforma especifica, ele também irá fazer o cache dos resultados, para utilizar posteriormente.
Compilador AOT
A experiência padrão para a maioria das cargas de trabalho do .NET é o compilador JIT, mas o .NET oferece duas formas de compilação de AOT (antecipação de tempo):
- Alguns cenários exigem a compilação da AOT de 100%. Um exemplo é Ios.
- Em outros cenários, a maior parte do código de um aplicativo é compilada pela AOT, mas algumas são compiladas por JIT. Alguns padrões de código não são amigáveis para a AOT (como os genéricos). Um exemplo dessa forma de compilação AOT é a opção de publicação pronta para execução . Essa forma de AOT oferece os benefícios da AOT sem suas desvantagens.
A ilustração a seguir mostra o relacionamento do Common Language Runtime e da biblioteca de classes com seus aplicativos e com o sistema geral. A ilustração também mostra como o código gerenciado opera dentro uma arquitetura maior.
Dada essa série de componentes do .NET, abaixo segue como elas se relacionam para fazer a compilação e execução do código.
- Escolha da linguagem e escrita do código
- Compilação do código em MSIL
- Compilação do MSIL em código nativo
- Execução do código
Para mais detalhes sobre o processo de compilação e execução do código acesse: Processo de execução gerenciada
Referências:
- Pro C# 8 with .NET Core 3 — Andrew Troelsen, Phil Japikse
- https://docs.microsoft.com/pt-br/dotnet/framework/get-started/overview
- https://docs.microsoft.com/pt-br/dotnet/core/introduction
- https://docs.microsoft.com/pt-br/dotnet/standard/managed-execution-process
- https://docs.microsoft.com/pt-br/dotnet/framework/migration-guide/versions-and-dependencies