Skip to content
 

Исследование механизма работы CLR(.NET)

Решил скопи-пастить статью для общего развития читающего. Суть в механизме работы, Америку не открываю но интересные моменты

В общем, платформа .NET включает в себя три основные сущности: CLR, CTS, CLS. Как мы уже узнали в предыдущей статье, CLR (Common Language Runtime) является сердцем платформы .NET. В её задачи, кроме всего прочего, входит управление потоками, памятью и безопасностью в процессе работы приложения. Также, CLR обеспечивает поиск, загрузку и управление используемых приложением .NET-типов.

Перед тем, как мы погрузимся в детали работы CLR, вспомним общую структуру самой .NET. В общем, платформа .NET включает в себя три основные сущности: CLR, CTS, CLS. Как мы уже узнали в предыдущей статье, CLR (Common Language Runtime) является сердцем платформы .NET. В её задачи, кроме всего прочего, входит управление потоками, памятью и безопасностью в процессе работы приложения. Также, CLR обеспечивает поиск, загрузку и управление используемых приложением .NET-типов. Теперь несколько слов о CTS (Common Type System) – общей системе типов. CTS описывает все возможные типы данных, которые поддерживаются CLR. Определяет их взаимодействие. Но, конкретный .NET-совместимый язык вполне может и не обеспечивать все возможности, предопределенные в CTS. CLS (Common Language Specification) – общеязыковая спецификация. Представляет собой описание (правила) подмножества типов и программных конструкций, на которые могут полагаться все .NET-совместимые языки. Таким образом, создав новый .NET-тип в строгом соответствии с CLS, мы гарантируем, что любой .NET-совместимый язык сможет использовать этот тип. На следующем рисунке показано взаимодействие рассмотренных структур с библиотекой базовых классов.


Рисунок 1. Взаимосвязь CLR и библиотеки базовых классов.

Итак, на сегодняшний день мы понимаем, что платформа .NET обеспечивает один строго определенный слой времени выполнения (CLR), который совместно используется всеми .NET-совместимыми языками и платформами. Грубо говоря, основная нагрузка на CLR ложится в момент определения расположения сборки и нахождение запрошенного типа в двоичном файле посредством чтения так называемых метаданных. Пока метаданные следует понимать как набор описательной информации. Но как же код, написанный нами, в конце-концов запускается и выполняется под некоторой операционной системой?! Разберем процесс создания исходного c#-кода и непосредственным выполнением его при запуске и работе приложения.

Итак, мы имеем исходный код, написанный на языке c#. Проект готов полностью и нам бы хотелось передать его кому бы то ни было для запуска. Прежде всего, нам необходимо c#-компилятором скомпилировать данный код в некий промежуточный код, так называемый MSIL-код (MSIL – это аббревиатура Microsoft Intermediate Language). Вообще то, мы можем использовать любой компилятор, но только соответствующий тому .NET-совместимому языку, на котором писался исходный код приложения. В данном случае мы использовали язык c#, а потому и компилировали c#-компилятором. На данном этапе мы получили промежуточный код в виде .exe, или .dll – файлов. Эти файлы называются сборками. Далее, при непосредственном запуске на выполнение этих файлов, CLR анализирует промежуточный код и загружает в память требуемые классы. Далее, с помощью JIT (Just In Time) компилятора преобразует промежуточный код в конкретный набор инструкций для данной платформы. И только после этого полученные инструкции запускаются на выполнение. На рисунке 2 продемонстрирован описанный только что процесс.


Рисунок 2. Компиляция исходного кода в исполняемый код.

Резонно задаться вопросом о необходимости промежуточной компиляции исходного кода. Казалось бы, к чему сперва проводить компиляцию в сборки, а уже только потом компилировать их в исполняемые инструкции? Ответ достаточно обширный, но базовой причиной тому является поддержка платформой .NET исходного кода множества различных языков программирования. Таким образом, независимо от того, на каком языке было написано приложение, при его запуске CLR всегда получает практически идентичный MSIL-код (сборки). Это дает преимущество в выборе любимого языка для разработки, а также использование нескольких языков при создании одного проекта.

Как я уже сказал, когда компилятор создает код MSIL, одновременно создаются метаданные. Метаданные содержат описание типов в коде, включая определение каждого типа, подписи каждого члена типа, члены, на которые есть ссылки в коде, а также другие сведения, используемые средой выполнения во время выполнения. Среда выполнения находит и извлекает метаданные из файла по мере необходимости при выполнении. Важно понимать, что JIT-компилятор не компилирует сразу весь код. Компиляция происходит «покусочно», по необходимости. То есть, компилируется тот участок кода, который непосредственно в данный момент должен пойти на выполнение. Однажды скомпилировав некоторый кусок кода, компилятор не удаляет его инструкции из памяти, а хранит на случай повторного вызова. Таким образом, однажды скомпилированный метод больше не компилируется и все его последующие неоднократные вызовы непосредственно обращаются к уже машинному коду. Но, также следует помнить, что JIT-компиляция происходит каждый раз при запуске приложения, ведь исходные исполняемые файлы приложения хранятся в виде сборок (.exe, .dll файлов). То есть каждый раз, при запуске приложения, CLR на лету подключает необходимые классы и выполняет JIT-компиляцию предоставляемых ему сборок.

взято skillcoding.com

Написать отзыв

Spam Protection by WP-SpamFree