Normalmente, el código compilado es el conjunto exacto de instrucciones que la CPU requiere para "ejecutar" el programa. En Java, el código compilado es un conjunto exacto de instrucciones para una "CPU virtual" que debe funcionar de la misma manera en cada máquina física.
Entonces, en cierto sentido, los diseñadores del lenguaje Java decidieron que el lenguaje y el código compilado iban a ser independientes de la plataforma, pero como el código finalmente tiene que ejecutarse en una plataforma física, optaron por poner todo el código dependiente de la plataforma en la JVM.
Este requisito para una JVM contrasta con el ejemplo de Turbo C. Con Turbo C, el compilador producirá código dependiente de la plataforma, y no hay necesidad de que una JVM funcione igual porque el programa Turbo C compilado puede ser ejecutado directamente por la CPU.
Con Java, la CPU ejecuta la JVM, que depende de la plataforma. Esta JVM en ejecución luego ejecuta el código de bytes de Java, que es independiente de la plataforma, siempre que tenga una JVM disponible para que se ejecute. Podría decir que al escribir código Java, no programa para que el código se ejecute en la máquina física, escribe el código para que se ejecute en la Máquina Virtual Java.
La única forma en que todo este código de bytes de Java funciona en todas las máquinas virtuales de Java es que se ha escrito un estándar bastante estricto sobre cómo funcionan las máquinas virtuales de Java. Esto significa que no importa qué plataforma física esté utilizando, se garantiza que la parte en la que el código de bytes de Java interactúa con la JVM funcionará de una sola manera. Dado que todas las JVM funcionan exactamente igual, el mismo código funciona exactamente igual en todas partes sin volver a compilar. Si no puede pasar las pruebas para asegurarse de que sea igual, no puede llamar a su máquina virtual "máquina virtual Java".
Por supuesto, hay formas de romper la portabilidad de un programa Java. Puede escribir un programa que busque archivos que solo se encuentran en un sistema operativo (cmd.exe, por ejemplo). Puede usar JNI, que efectivamente le permite poner código C o C ++ compilado en una clase. Puede utilizar convenciones que solo funcionen para un determinado sistema operativo (como suponer que ":" separa directorios). Pero está garantizado que nunca tendrá que volver a compilar su programa para una máquina diferente a menos que esté haciendo algo realmente especial (como JNI).