2.17.4 Инициализация
Инициализация класса состоит из:
- выполняет свои статические инициализаторы (§2.11) и
- инициализаторы для статических полей (§2.9.2), объявленные в классе.
Инициализация интерфейса состоит из выполнения инициализаторов для полей, объявленных в интерфейсе (§2.13.3.1).
Прежде чем класс или интерфейс инициализируются, его прямой суперкласс должен быть инициализирован, но интерфейсы, реализуемые классом, не должны инициализироваться. Аналогичным образом, суперинтерфейсы интерфейса не нужно инициализировать до инициализации интерфейса.
Класс T или интерфейс типа T будут инициализированы непосредственно перед тем, как произойдет одно из следующих действий:
- T является классом, и создается экземпляр T.
- T является классом и вызывается статический метод T.
- Используется или присваивается непостоянное статическое поле T. Поле констант - это поле, которое (явно или неявно) является как конечным, так и статическим, и которое инициализируется значением константного выражения во время компиляции. Ссылка на такое поле должна быть преобразована во время компиляции в копию значения константы во время компиляции, поэтому использование такого поля никогда не вызывает инициализацию.
Вызов определенных методов в библиотечных классах (§3.12) также вызывает инициализацию класса или интерфейса. Подробности см. В спецификациях библиотеки классов платформы Java 2 (например, класс Class и пакет java.lang.reflect).
Намерение здесь состоит в том, чтобы тип имел набор инициализаторов, переводящих его в согласованное состояние, и чтобы это состояние было первым состоянием, которое наблюдается другими классами. Статические инициализаторы и инициализаторы переменных класса выполняются в текстовом порядке и могут не ссылаться на переменные класса, объявленные в классе, объявления которых появляются текстуально после использования, даже если эти переменные класса находятся в области видимости. Это ограничение предназначено для обнаружения во время компиляции большинства циклических или неправильно сформированных инициализаций.
Перед инициализацией класса или интерфейса его суперкласс инициализируется, если он не был инициализирован ранее.
Инициализация класса или интерфейса состоит из выполнения метода инициализации его класса или интерфейса ( §2.9 ).
Класс или интерфейс могут быть инициализированы только в результате:
- Выполнение любой из инструкций виртуальной машины Java
new
, getstatic
, putstatic
или invokestatic
, которые ссылаются на класс или интерфейс (§new
, §getstatic
, §putstatic
, §invokestatic
).
Все эти инструкции ссылаются на класс прямо или косвенно через ссылку на поле или ссылку на метод.
После выполнения новой инструкции указанный класс или интерфейс инициализируется, если он еще не был инициализирован.
При выполнении инструкции getstatic
, putstatic
или invokestatic
класс или интерфейс, который объявил разрешенное поле или метод, инициализируется, если он еще не был инициализирован.
- Первый вызов
java.lang.invoke.MethodHandle
экземпляра, который был результатом разрешения дескриптора метода виртуальной машиной Java ( §5.4.3.5 ) и который имеет вид 2 (REF_getStatic
), 4 (REF_putStatic
), 6 (REF_invokeStatic
) или 8 (REF_newInvokeSpecial
).
- Вызов определенных рефлексивных методов в библиотеке классов ( §2.12 ), например, в классе
Class
или в пакете java.lang.reflect
.
- Инициализация одного из его подклассов.
- Его обозначение как начальный класс при запуске виртуальной машины Java ( §5.2 ).
Перед инициализацией класс или интерфейс должны быть связаны, то есть проверены, подготовлены и при необходимости разрешены .
Поскольку виртуальная машина Java является многопоточной, инициализация класса или интерфейса требует тщательной синхронизации, поскольку некоторые другие потоки могут пытаться инициализировать тот же класс или интерфейс в одно и то же время.
Также существует вероятность того, что инициализация класса или интерфейса может быть запрошена рекурсивно как часть инициализации этого класса или интерфейса.
Реализация виртуальной машины Java отвечает за обеспечение синхронизации и рекурсивной инициализации с помощью следующей процедуры.
Предполагается, что объект Class
уже был проверен и подготовлен и что объект Class
содержит состояние, которое указывает на одну из четырех ситуаций:
- Этот
Class
объект проверен и подготовлен, но не инициализирован.
- Этот
Class
объект инициализируется каким-то конкретным потоком.
- Этот
Class
объект полностью инициализирован и готов к использованию.
- Этот
Class
объект находится в ошибочном состоянии, возможно, из-за попытки инициализации и неудачи.