Любое такое утверждение о том, что делают «переводчики», подлежит наблюдению, что не все переводчики одинаковы.
Например, интерпретатор Python берет исходные файлы .py и запускает их. По дороге он генерирует «скомпилированные» файлы .pyc. В следующий раз, когда вы запустите те же файлы .py, этап «компиляции» можно пропустить, если файлы .py не были изменены. (Я говорю «компиляция» в кавычках, поскольку AFAIK результат не машинный код).
Теперь перейдем к Java. Конечно, система Java могла бы быть спроектирована так, чтобы компилятор Java выводил модули машинного кода (или, что то же самое, файлы кода сборки), которые затем могли быть связаны в машинно-исполняемый образ. Но дизайнеры не хотели этого делать. Они специально предназначались для компиляции в набор команд виртуальной машины, последняя интерпретирует байт-код.
Со временем JVM начали оптимизировать секции байт-кода, переводя их в машинный код. Но это не то же самое, что перевод целых программ.
Что касается компромисса / интерпретации: один из факторов - это как долго выполняется ваша программа и как долго она будет меняться. Если вы используете короткие «студенческие» программы, которые, скорее всего, выполняются только один раз перед изменением, нет смысла вкладывать много усилий в компиляцию. С другой стороны, если ваша программа управляет устройством, которое, вероятно, будет включено в течение нескольких недель, компиляция JIT в устройстве стоит того, и повторять ее после перезагрузки устройства не составляет особого труда.
Некоторые из нас, кто пишет код Java, работающий на одной конкретной аппаратной конфигурации, могут предпочесть «скомпилировать все целиком и покончить с этим», но это не тот подход, который использовался этим конкретным языком. Я полагаю, что в принципе кто-то мог бы написать этот компилятор, но его несуществование, кажется, подтверждает, что нет никакого стимула для этого.