Как правило, скомпилированный код представляет собой точный набор инструкций, необходимых процессору для «выполнения» программы. В Java скомпилированный код представляет собой точный набор инструкций для «виртуального процессора», который должен работать одинаково на каждой физической машине.
Итак, в некотором смысле разработчики языка Java решили, что язык и скомпилированный код будут независимыми от платформы, но, поскольку код в конечном итоге должен выполняться на физической платформе, они решили поместить весь код, зависящий от платформы, в JVM.
Это требование для JVM отличается от вашего примера Turbo C. С Turbo C компилятор будет создавать код, зависящий от платформы, и нет необходимости в подобной работе JVM, потому что скомпилированная программа Turbo C может быть выполнена непосредственно ЦП.
В Java ЦП выполняет JVM, которая зависит от платформы. Эта запущенная JVM затем выполняет байт-код Java, который не зависит от платформы, при условии, что у вас есть JVM, доступная для его выполнения. Вы можете сказать, что при написании кода Java вы не программируете код, который будет выполняться на физической машине, вы пишете код, который будет выполняться на виртуальной машине Java.
Единственный способ, которым весь этот байт-код Java работает на всех виртуальных машинах Java, - это то, что был написан довольно строгий стандарт того, как работают виртуальные машины Java. Это означает, что независимо от того, какую физическую платформу вы используете, часть, в которой байт-код Java взаимодействует с JVM, гарантированно будет работать только в одном направлении. Поскольку все JVM работают одинаково, один и тот же код работает одинаково везде без перекомпиляции. Если вы не можете пройти тесты, чтобы убедиться, что это то же самое, вам не разрешается называть свою виртуальную машину «виртуальной машиной Java».
Конечно, есть способы, которыми вы можете нарушить переносимость Java-программы. Вы можете написать программу, которая ищет файлы только в одной операционной системе (например, cmd.exe). Вы можете использовать JNI, который эффективно позволяет вам помещать скомпилированный код C или C ++ в класс. Вы можете использовать соглашения, которые работают только для определенной операционной системы (например, предположение, что ":" разделяет каталоги). Но вам гарантировано, что вам никогда не придется перекомпилировать вашу программу для другой машины, если вы не делаете что-то действительно особенное (например, JNI).