Я немного запутался в деталях работы компилятора JIT. Я знаю, что С# компилируется до IL. При первом запуске это JIT'd. Это связано с тем, что он переводится в собственный код? Является ли среда выполнения .NET(как виртуальная машина?) Взаимодействовать с кодом JIT'd? Я знаю, что это наивно, но я действительно смутил себя. Мое впечатление всегда заключалось в том, что сборки не интерпретируются .NET Runtime, но я не понимаю деталей взаимодействия.
С# JIT компиляция и .NET
Ответ 1
Да, код JIT'ing IL включает в себя перевод IL в собственные машинные инструкции.
Да, среда выполнения .NET взаимодействует с собственным машинным кодом JIT'ed, в том смысле, что среда выполнения имеет блоки памяти, занятые собственным машинным кодом, вызовы во время выполнения в собственный машинный код и т.д.
Вы правы, что среда выполнения .NET не интерпретирует код IL в ваших сборках.
Что происходит, когда выполнение достигает функции или блока кода (например, else else блока if), который еще не был JIT, скомпилированный в собственный машинный код, JIT'r вызывается для компиляции этого блока IL в собственный машинный код. Когда это будет сделано, выполнение программы вводит свежеиспеченный машинный код для выполнения его программной логики. Если при выполнении этого собственного машинного кода выполнение вызова функции функции, которая еще не скомпилирована для машинного кода, JIT'r вызывается для компиляции этой функции "как раз вовремя". И так далее.
JIT'r не обязательно компилирует всю логику тела функции в машинный код сразу. Если в функции есть операторы if, блоки операторов команд if и else могут не быть скомпилированы JIT до тех пор, пока выполнение не пройдет через этот блок. Пути кода, которые не выполнялись, остаются в форме IL до тех пор, пока они не выполняются.
Скомпилированный исходный машинный код хранится в памяти, так что его можно будет использовать снова в следующий раз, когда будет выполняться раздел кода. Во второй раз, когда вы вызываете функцию, она будет работать быстрее, чем в первый раз, когда вы ее вызовете, потому что во второй раз не нужно делать шаг JIT.
На настольном компьютере .NET собственный машинный код хранится в памяти на всю жизнь приложения. В .NET CF нативный машинный код может быть выброшен, если приложение работает с низким объемом памяти. Это будет JIT, скомпилированный снова из исходного кода IL, в следующий раз, когда выполнение пройдет через этот код.
Ответ 2
Код "компилируется" на Microsoft Intermediate Language, который похож на формат сборки.
При двойном щелчке по исполняемому файлу Windows загружает mscoree.dll
, который затем устанавливает среду CLR и запускает ваш программный код. Компилятор JIT начинает считывать код MSIL в вашей программе и динамически компилирует код в инструкции x86, которые процессор может выполнить.
Ответ 3
Если вам интересна книга по теме IL и материала нижнего уровня в .NET, я бы предложил посмотреть CLR через С#.
Ответ 4
.NET использует промежуточный язык, называемый MSIL, иногда сокращенный как IL. Компилятор читает ваш исходный код и производит MSIL. Когда вы запускаете программу, компилятор .NET Just In Time (JIT) читает ваш код MSIL и создает исполняемое приложение в памяти. Вы не увидите ничего подобного, но это хорошая идея знать, что происходит за кулисами.
Ответ 5
Я расскажу о том, как скомпилировать IL-код в инструкции по внутреннему процессору, как показано ниже.
public class Example
{
static void Main()
{
Console.WriteLine("Hey IL!!!");
}
}
В первую очередь CLR знает каждую информацию о типе и том, какой метод вызывается из этого типа, из-за метаданных.
Когда CLR начинает выполнять IL в командную команду CPU, CLR времени выделяет внутренние структуры данных для каждого типа, на который ссылается основной код.
В нашем случае у нас есть только один тип Console, поэтому CLR будет выделять одну внутреннюю структуру данных через эту внутреннюю структуру, мы будем управлять доступом к ссылочным типам
внутри этой структуры данных CLR имеет записи обо всех методах, определенных этим типом. Каждая запись содержит адрес, в котором может быть найдена реализация методов.
При инициализации этой структуры CLR устанавливает каждую запись в недокументированной FUNCTION, содержащейся внутри самой CLR. И, как вы можете догадаться, эта FUNCTION - это то, что мы называем JIT Compiler.
В целом вы могли бы рассмотреть JIT Compiler как функцию CLR, которая собирает IL в собственные инструкции процессора. Позвольте мне подробно показать вам, как этот процесс будет в нашем примере.
1. Когда Main делает свой первый вызов WriteLine, вызывается функция JITCompiler.
2.JIT Функция компилятора знает, какой метод вызывается и какой тип определяет этот метод.
3. Затем Jit Compiler ищет сборку, где определен этот тип и получает IL-код для метода, определенного этим типом, в нашем случае IL-код метода WriteLine.
4.JIT компилятор выделяет DYNAMIC блок памяти, после чего JIT проверяет и компилирует IL-код в собственный код ЦП и сохраняет этот код ЦП в этом блоке памяти.
5. Затем компилятор JIT возвращается к записи внутренней структуры данных и заменяет адрес (который в основном ссылается на реализацию кода IL-кода WriteLine) с новым динамически созданным блоком памяти с адресами, которые содержат собственные инструкции процессора WriteLine.
6. Наконец, функция JIT Compiler переходит к коду в блоке памяти. Этот код представляет собой реализацию метода WriteLine.
7. После реализации WriteLine код возвращается к Mains'code, который продолжает выполнение как обычно.
Ответ 6
.NET Framework использует среду CLR для создания MSIL (Microsoft Intermediate Language), также называемого IL. Компилятор читает ваш исходный код, и когда вы собираете/компилируете свой проект, он генерирует MSIL. Теперь, когда вы наконец запустите свой проект, в действие вступит .NET JIT (Just-in-time Compiler). JIT читает ваш код MSIL и создает собственный код (который является инструкциями x86), который может быть легко выполнен CPU. JIT читает все инструкции MSIL и выполняет их построчно.
Если вам интересно посмотреть, что происходит за кулисами, на это уже есть ответ. Пожалуйста, следуйте - Здесь