Виртуальная машина, как и JVM, - это программа, которая принимает в качестве входных данных, обычно файлы, набор простых инструкций (которые обычно легко преобразовать в настоящие инструкции ЦП) и фактически компилирует и запускает их как собственные инструкции ЦП (обычно с использованием компилятор по требованию, такой как HotSpot или JIT).
По сути это слой абстракции. Обычно гораздо проще портировать реализации набора команд VM на разные архитектуры процессоров из-за нескольких сходств (например, на основе стека). Кроме того, гораздо проще портировать разные языки программирования на команды виртуальных машин, поскольку они больше ориентированы на современные языки программирования, чем на примитивные инструкции процессора. Многие виртуальные машины, такие как JVM и CLR (.NET), содержат инструкции для вызова виртуальных методов и создания экземпляров объектов.
Итак, давайте возьмем язык для примера. Назовите это MyLanguage. Поскольку это язык программирования, он в конечном итоге сводится к набору некоторых инструкций архитектуры процессора. Это означает, что при наличии совместимого гибкого набора команд виртуальной машины также возможно скомпилировать MyLanguage до набора инструкций этой виртуальной машины.
Всегда есть вопрос эффективности, так как вам, возможно, придется взломать некоторые обходные пути в наборах команд виртуальных машин, которые вам не придется делать изначально, но это все же возможно.