El elemento clave en esto es la separación de la compilación de la fase de ejecución. Con esto es posible escribir otros compiladores compilando otros idiomas para bytecode.
El código de bytes allí actúa de manera similar al código de máquina de una CPU: tiene todas las pequeñas operaciones necesarias para ejecutar un programa; puede obtener una variable, hacer cálculos matemáticos, operaciones condicionales, etc.
Java tampoco es especial. En Java, la existencia de múltiples idiomas ni siquiera era un objetivo de diseño, a diferencia de otras máquinas virtuales. Para Microsoft .Net CIL, la capacidad de ejecutar múltiples idiomas (C #, VB.Net, ...) fue un elemento de diseño clave, también el ParrotVM del proyecto Perl6 destinado a ser una VM genérica.
Por diversión, una vez creé una prueba de que incluso el motor Zend de PHP lo permitiría.
Y, francamente, esto no es nada nuevo, incluso en hardware real puede ejecutar múltiples idiomas, es decir, C o Fortran.
La diferencia con esta separación de la compilación y la ejecución son los intérpretes clásicos, como algunas formas de Basic, scripts de shell, etc. A menudo funcionan de manera que ejecutan código más o menos línea por línea sin traerlo de forma inmediata. entre.