Una macchina virtuale, come la JVM, è un programma che accetta come input, di solito file, una serie di semplici istruzioni (che di solito sono facili da convertire in vere istruzioni della CPU), e in realtà le compila e le esegue come istruzioni native della CPU (solitamente utilizzando un compilatore on-demand come HotSpot o JIT).
È essenzialmente uno strato di astrazione. In genere è molto più semplice eseguire il porting di implementazioni di set di istruzioni VM su architetture di processori diverse, a causa di molte somiglianze (come lo stack). È anche molto più facile trasferire diversi linguaggi di programmazione in istruzioni VM, dal momento che è più orientato verso i moderni linguaggi di programmazione rispetto alle primitive istruzioni della CPU. Molte macchine virtuali come JVM e CLR (.NET) contengono istruzioni per chiamare metodi virtuali e creare istanze di oggetti.
Quindi prendiamo un linguaggio per esempio. Chiamalo MyLanguage. Dal momento che si tratta di un linguaggio di programmazione, alla fine viene compilato su un insieme di alcune istruzioni di architettura della CPU.
Ciò significa che, dato un set di istruzioni Virtual Machine compatibile e flessibile, è anche possibile compilare MyLanguage su un set di quelle istruzioni della VM.
C'è sempre una questione di efficienza, dal momento che potrebbe essere necessario modificare alcuni workaround nei set di istruzioni VM che non dovresti fare in modo nativo, ma è ancora possibile.