Подтвердить что ты не робот

Является ли CLR виртуальной машиной?

Я прочитал книгу, которая ссылалась на .net CLR как на виртуальную машину? Кто-нибудь может это оправдать? В чем причина, по которой нам нужна концепция виртуальных машин на некоторых платформах разработки?

Невозможно ли создать встроенную инфраструктуру (без виртуальной машины), которая полностью объектно ориентирована и столь же мощна, как .net?

В книге, которая ссылается на CLR как на виртуальную машину, " Professional.Net Framework 2.0".

4b9b3361

Ответ 1

Здесь много заблуждений. Полагаю, вы могли бы подумать .Net как виртуальную машину, если хотите, но посмотрите, как .NET Framework действительно обрабатывает ваш код. Типичный сценарий выглядит следующим образом

  • Вы пишете программу .Net на языках С#, VB.Net, F # или на другом совместимом языке.
  • Этот код скомпилирован до промежуточного языка (IL), который похож на байт-код Java, который распространяется на компьютеры конечного пользователя.
  • Конечный пользователь впервые запускает программу на компьютере с правильной версией установленной .Net
  • Компьютер видит, что это сборка .Net, а не "сырой" машинный код и передает ее компилятору JIT
  • Компилятор JIT компилирует IL в полностью собственный машинный код.
  • Нативный код сохраняется в памяти в течение всего срока выполнения этой программы.
  • Вызывается сохраненный код, и IL больше не имеет значения.

Здесь есть пара важных моментов, но большая заключается в том, что ни в коем случае какой-либо код никогда не интерпретируется. Вместо этого на шаге 5 вы можете увидеть, что он скомпилирован в собственный код. Это огромная разница, чем загрузка его в виртуальную машину по нескольким причинам:

  • Полностью скомпилированный код выполняется процессором напрямую, а не интерпретируется или переводится с помощью дополнительного слоя абстракции программного обеспечения, который должен быть быстрее.
  • Компилятор JIT может использовать преимущества оптимизации, характерные для отдельной машины, запускающей программу, а не для определения самого низкого общего знаменателя.
  • Если вы хотите, вы даже можете предварительно скомпилировать код и по существу полностью скрыть шаг 5 от пользователя.

Я полагаю, вы могли бы назвать это виртуальной машиной, в том смысле, что JITter абстрагирует детали реальной машины от разработчика. Лично я не думаю, что это действительно так, потому что для многих людей виртуальная машина подразумевает абстракцию времени выполнения от собственного кода, который для программ .Net просто не существует.

Еще один ключевой момент в отношении всего этого процесса, который действительно отличает его от среды "виртуальной машины", заключается в том, что это только типичный процесс. Если вы действительно этого захотите, вы можете предварительно скомпилировать сборку .Net перед распространением и развернуть собственный код непосредственно для конечных пользователей (подсказка: она медленнее в совокупности в течение всего срока службы программы, потому что вы теряете оптимизацию для конкретной машины). Разумеется, вам все равно потребуется установленная среда .Net, но на данный момент она действительно не сильно отличается от любого другого API среды выполнения; он больше похож на коллекцию dll с хорошим API, с которым вы можете ссылаться, поскольку это может быть связано с временем выполнения VB или C. Microsoft также поставляется с Visual Studio. Этот вид берет IL из фотографии, делая прозвище VM намного труднее оправдать. (Я говорю "вид", потому что IL все еще развернут и используется для проверки сохраненного кода, но он никогда не касался его для выполнения).

Другим важным моментом является отсутствие процесса виртуальной машины. При запуске приложения нет обычного процесса "песочницы". Сравните это с Java, где, если вы откроете диспетчер задач при запуске программы, вы увидите процесс, специально предназначенный для виртуальной машины Java, а фактический процесс приложения - это поток внутри изолированной среды, созданной виртуальной машиной. В .Net вы видите процесс приложения непосредственно в диспетчере задач Windows.

Вкратце: вы могли бы сказать, что IL + CLR + JIT вместе каким-то образом составляют виртуальную машину. Лично я так не думаю, но я не буду спорить с вами, если вы этому поверили. То, что я хочу сделать, это то, что когда вы говорите кому-то, что .Net работает на виртуальной машине без каких-либо дополнительных объяснений, идея, которую вы общаетесь с этим человеком, - это "интерпретируемый байт-код в хост-процессе". И это просто неправильно.

Ответ 2

Подобно виртуальной машине Java (JVM),.net CLR представляет собой виртуальную машину, интерпретирующую байтовый код.

JVM интерпретирует программы, которые содержат java-байтовые коды, и .net CLR интерпретирует программы, которые содержат то, что Microsoft называет инструкциями Intermediate Language (IL). Существуют различия между этими байтовыми кодами, но виртуальные машины схожи и стремятся предоставить аналогичные функции.

Обе эти версии виртуальной машины имеют возможность компилировать свой входной байт-код на машинный язык компьютера, на котором они запущены. Это называется "Just In Time Compilation (JIT)", а полученный выходной код называется "JIT-код". Поскольку код JIT содержит последовательности инструкций на машинных языках компьютерного ЦП, этот код иногда называют "родным" кодом.

Однако JIT-код качественно и количественно отличается от кода на основе, как объясняется ниже. По этой причине в этой статье JIT-код представляет собой не что иное, как встроенную реализацию виртуальной машины при запуске конкретной программы байт-кода.

Одна из возможностей, которую обе эти виртуальные машины (VM) стремятся предоставить, - это безопасность в виде предотвращения некоторых опасных ошибок программирования. Например, заголовок этого веб-форума, stackoverflow, вдохновлен одним из таких опасных ошибок, который возможен в собственном коде.

Чтобы обеспечить безопасность и безопасность выполнения, виртуальные машины реализуют безопасность типов на уровне "Виртуальная машина". Назначения памяти VM необходимы для хранения типа данных, которые хранятся в этой ячейке памяти. Например, если целое число вставляется в стек, невозможно вытащить двойной из стека. C-style "союзы" запрещены. Указатели и прямой доступ к памяти запрещены.

Мы не могли получить такие же преимущества, применяя объектно-ориентированную языковую среду для разработчиков, если результатом является собственный двоичный файл, такой как EXE файл. В этом случае мы не сможем различать исходные двоичные файлы, сгенерированные с использованием фреймворка и EXE, создаваемые злоумышленником, использующим источники, отличные от структуры.

В случае виртуальных машин безопасность типа применяется на "самом низком уровне", к которому программисту разрешен доступ. (Пренебрегая на мгновение тем, что можно написать управляемый собственный код, то есть.) Поэтому ни один пользователь не столкнется с приложением, которое выполняет одну из опасных операций, требующих прямого доступа к ячейкам памяти и указателям.

На практике CLR.NET реализует способ записи собственного кода, который может быть вызван кодом "управляемого".net. В этом случае бремя лежит на автору собственного кода, чтобы не делать ошибок указателя и памяти.

Поскольку как JVM, так и .net CLR выполняют компиляцию JIT, либо виртуальная машина фактически создает двоичный код с исходным кодом из поставленного байткода. Этот "JIT-код" выполняется быстрее, чем выполнение интерпретатора виртуальной машины, потому что даже код машинного языка, созданный JIT, содержит все необходимые VM-проверки безопасности, которые будет выполнять VM. В результате код вывода JIT не так быстро, как собственный код, который обычно не содержит многочисленных проверок времени выполнения. Однако этот недостаток производительности скорости заменяется на улучшение надежности, включая безопасность; в частности, предотвращается использование неинициализированного хранилища, соблюдается безопасность типов назначений, выполняется проверка диапазона (таким образом предотвращается переполнение буфера и кучи), время жизни объектов управляется сбором мусора, динамическое распределение безопасно по типу. Среда, выполняющая такие проверки поведения во время выполнения, реализует спецификацию виртуальной машины и представляет собой немного больше, чем реализация машинного языка виртуальной машины.

Ответ 3

Часть "Виртуальная машина" относится к тому факту, что .NET-код скомпилирован в EXE и DLL в качестве "промежуточного" языка ассемблера (IL) для запуска на виртуальной машине, в отличие от реального языка сборки процессора. Затем во время выполнения ILM преобразуется в реальную сборку процессора для выполнения (называется "точно вовремя" или компиляция JIT).

Конечно, вы могли бы написать компилятор .NET, чтобы он был скомпилирован на языке ассемблера процессора вместо IL. Однако это не было бы переносимым для всех процессоров - вам придется составлять другую версию для каждой пары ОС/ЦП. Но, компилируя в ILM, вы позволяете "виртуальной машине" обрабатывать специфичные для процессора и ОС вещи.

Ответ 4

Преимуществом CLR является свобода писать код на любом языке программирования, который разработчик выбирает, поскольку код будет скомпилирован до CLR, прежде чем будет интерпретироваться в native-вызовах..NET framework использует эту компиляцию JIT для обработки всех равномерно и выходных программ, которые работают для развернутой платформы, которая отсутствует на скомпилированных языках.

Ответ 5

Я немного старая школа, поэтому я называю CLR виртуальной машиной. Мое рассуждение состоит в том, что CLR собирает машинный код из промежуточного байт-кода, что и делает виртуальная машина.

Преимущества CLR в основном связаны с тем, как он собирает машинный код, который использует информацию типа времени выполнения.

Вы можете создать собственную среду, столь же мощную, как и .NET framework, используя только родные типы. Единственная гибкость, которую вы теряете, - это возможность собирать собственный код, если вы когда-либо переносите свою программу на другую платформу без перекомпиляции.

Ответ 6

Ни JVM, ни CLR не делают ничего существенного, чем то, что делает большинство "виртуальных машин" для других языков. В настоящее время все они используют JIT для преобразования виртуальных инструкций (p-code, байт-коды, инструкции по промежуточному языку, называет их любыми, как вам нравится) инструкциям "встроенного процессора" ( "машинный код" ).

Фактически первой виртуальной машиной для этого была виртуальная машина Smalltalk. Автор этого нововведения Питер Дойч назвал его "динамическим переводом" вместо термина "JIT", который был популяризирован Java. Если средоточность исполнения "Smalltalk" будет называться "виртуальной машиной" (и тем, что она еще вызывает), тогда любая и всякая "система времени выполнения", которая по сути делает то же самое, также квалифицируется как "виртуальные машины". "

Ответ 7

У вас много ценных ответов, но я думаю, что еще не было упомянуто: модульность.

Очень сложно экспортировать OO-класс из родной DLL. Конечно, вы можете сказать компоновщику, чтобы экспортировать класс и импортировать его где-то в другом месте, но это хрупкое; Изменение одного частного члена в классе приведет к нарушению бинарной совместимости, т.е. Если вы измените одну DLL без перекомпиляции всех других модулей, ваша программа будет ужасно грохотаться во время выполнения.

Существует несколько способов: например, вы можете определить публичные абстрактные интерфейсы, извлечь из них и экспортировать глобальные функции factory из вашей DLL. Таким образом, вы можете изменить детали реализации класса. Но вы не можете получить этот класс в другой DLL. И, конечно же, изменение интерфейса также ломает двоичную совместимость.

Я не уверен, есть ли хорошее решение для этого в собственном коде: если компилятор/компоновщик создает собственный код во время компиляции, он должен знать точный макет памяти классов/структур, которые используются в коде, Если последний шаг компиляции (генерация собственного кода) задерживается до тех пор, пока метод не будет вызван в первый раз, эта проблема просто исчезнет: вы можете изменить класс в сборке и до тех пор, пока JIT может разрешить все используемые члены в время выполнения, все будет нормально работать.

В двух словах: если вы создаете монолитную однозадачную программу, возможно, у вас может быть большинство мощных функций .NET с компилятором, который создает собственный код. Но недостатки наличия JIT-компилятора (установка инфраструктуры, несколько более длительные периоды запуска) действительно не перевешивают преимущества в большинстве случаев.