Наличие интерпретатора - это деталь реализации, которая не имеет отношения к описанию поведения программы. В принципе, можно иметь JVM вообще без интерпретатора, поскольку в нем может быть только компилятор, который переводит весь байт-код в собственный код перед выполнением и при этом реализует правильное поведение. В текущих версиях JVM для настольных компьютеров и серверов они выполняют код в смешанном режиме.
Таким образом, также не имеет значения, когда блоги и видео упоминают о существовании интерпретатора как способа выполнения кода, выполнение кода всегда подразумевает наличие технических средств для выполнения кода, таких как интерпретатор или компилятор. .
Фактическое поведение было указано в Спецификация языка Java, §12.4.1 :
§12.4.1. Когда происходит инициализация
Класс T или интерфейсный тип T будут инициализированы непосредственно перед первым появлением любого из следующего:
T
является классом, и создается экземпляр T
.
- Метод
static
, объявленный T
, вызывается.
- Назначено поле
static
, объявленное T
.
- Используется поле
static
, объявленное T
, и поле не является константной переменной ( §4.12.4 ).
T
- это класс верхнего уровня ( §7.6 ) и оператор assert
( §14.10 ), лексически вложенный в T
( §8.1.3 ) выполняется. ¹
Когда класс инициализируется, инициализируются его суперклассы (если они не были предварительно инициализированы), а также любые суперинтерфейсы ( §8.1.5 ), которые объявляют любые методы по умолчанию ( § 9.4.3 ) (если они не были предварительно инициализированы). Инициализация интерфейса сама по себе не вызывает инициализацию любого из его суперинтерфейсов.
last последняя пуля была удалена из новых спецификаций
Поскольку вызов метода main
является вызовом «метода static
, объявленного» вашим классом, это подразумевает инициализацию этого класса до вызова. Как можно понять из последнего раздела, если класс, содержащий метод main
, имеет неинициализированные суперклассы, они инициализируются еще до этого класса.
Для стандартного средства запуска Java порядок событий
- Основной поток создан
- Основной поток загружает указанный класс приложения
- Суперклассы класса приложения инициализируются, если еще не инициализированы
- Класс приложения инициализирован
- Метод
static void main(String[])
вызывается в классе приложения
Термины «класс приложения» и «основной класс» являются взаимозаменяемыми.
Обратите внимание, что этот список предназначен только для упорядочения этих событий. За кулисами происходит гораздо больше событий. Очевидно, что для запроса загрузчика класса приложения загрузить класс приложения, заданный по имени, классы String
, Class
и ClassLoader
должны быть загружены и инициализированы, что также подразумевает, что их суперкласс Object
был инициализирован еще до этого. Существование основного потока подразумевает загрузку и инициализацию класса Thread
. И все эти классы используют другие классы за кулисами.
Вы можете запустить ваше приложение с опцией -verbose:class
, чтобы увидеть, какие классы уже загружены до вашего класса приложения.