Una máquina virtual, como JVM, es un programa que acepta como entrada, generalmente archivos, un conjunto de instrucciones simples (que generalmente son fáciles de convertir a instrucciones reales de CPU), y en realidad las compila y ejecuta como instrucciones de CPU nativas. (por lo general, utiliza un compilador a pedido, como HotSpot o JIT).
Es esencialmente una capa de abstracción. Por lo general, es mucho más fácil trasladar implementaciones de conjuntos de instrucciones de VM a diferentes arquitecturas de procesadores, debido a varias similitudes (como estar basado en la pila). También es mucho más fácil portar diferentes lenguajes de programación a las instrucciones de la máquina virtual, ya que está más orientado a los lenguajes de programación modernos que las instrucciones primitivas de la CPU. Muchas máquinas virtuales como JVM y CLR (.NET) contienen instrucciones para llamar a métodos virtuales y crear instancias de objetos.
Por ejemplo, tomemos un lenguaje. Llámalo MyLanguage. Dado que es un lenguaje de programación, en última instancia, se compila en un conjunto de instrucciones de arquitectura de CPU.
Eso significa que, dado un conjunto de instrucciones de máquina virtual flexible y compatible, también es posible compilar MyLanguage en un conjunto de instrucciones de esa máquina virtual.
Siempre hay una cuestión de eficiencia, ya que es posible que deba piratear algunas soluciones en los conjuntos de instrucciones de VM que no tendría que hacer de forma nativa, pero aún es posible.