Я только что закончил чтение спецификации виртуальной машины Java, и section on class loading оставил меня озадаченным. Насколько я понял, в целом, и после прочтения спецификации, я думал, что общая конкретизации класса состоит из следующих шагов в следующем порядке:Где начинается этап разрешения загрузки класса Java?
Создание/Загрузка: Класс loader находит поток байтов, представляющий класс, либо файл, либо сетевой поток, либо все, что реализует загрузчик классов для извлечения. Если ни один класс не найден, выдается
ClassNotFoundException
. На этом этапе уже происходит некоторая базовая проверка, когда возникаетClassFormatError
, если массив байтов не представляет собой класс Java (например, магическое число отсутствует) илиUnsupportedClassVersionError
, если версия класса не поддерживается работающей JVM пример.Ссылка: Класс подключен к JVM. Если что-то пойдет не так, подкласс
LinkageError
брошен. Linking состоит из трех подэтапов:Проверка: Это удостоверяется, что поток байт представляет собой класс Java, как, например, что байты-код без формальных ошибок, таких как переполненные операндов стека для байт-коды методы , Если класс не прошел проверку, выдается
VerifyError
.Подготовка: JVM выделяет память для всех статических полей и может создать шаблон экземпляра для ускорения создания экземпляра. Создаются таблицы виртуальных методов. На этом этапе не будут выбраны конкретные ошибки загрузки классов. (An
OutOfMemoryError
может быть выброшен, хотя.)Разрешение: Все символические ссылки, которые теперь были загружены в область метода в виде выполнения постоянная бассейна разрешены к реальным типам загруженных этой виртуальной машины Java. Если символическая ссылка может быть разрешена, но приводит к конфликту определений, то вызывается
IncompatibleClassChangeError
. Если ссылочный класс не найден, вызываетсяNoClassDefFoundError
, который в основном обертываетClassNotFoundException
, который был брошен загрузчиком класса, пытающимся загрузить этот ссылочный класс. Если ссылочный класс ссылается на себя, бросаетсяClassCircularityError
. Разрешение может произойти в одном из двух ароматов, который составляет до реализаторов в JVMEager: Все символические ссылки на другие поля, методы и классы будут решены прямо сейчас.
Lazy: Разрешение символических ссылок откладывается до первого использования метода. Это может привести к тому, что класс, ссылающийся на несуществующий класс, никогда не выдает ошибку, если эта ссылка никогда не нуждается в разрешении.
Initialization:
static
Инициализаторы Класс, что определены в классе как Java кода выполняются.Если исключение вызвано таким инициализатором, это исключение перевернуто вExceptionInInitializerError
.
Что меня озадачивает это разрешение фаза выше механизма загрузки класса. Почему разрешение определено как явный шаг в пределах , связывающий, который происходит специально после препарата? Уже в description of the class loading phase упоминается, что
Если C имеет какие-либо прямые суперинтерфейсов, символические ссылки от С до его прямые суперинтерфейсы разрешаются с использованием алгоритма §5.4.3.1.
ли символические ссылки также не решен в то время как проверка происходит, так как проверка described:
Проверка (§4.10) гарантирует, что двоичное представление или интерфейс класса является структурно правильным (§4.9). При проверке могут возникнуть дополнительные классы и интерфейсы (§5.3), но не обязательно заставляют их проверять или подготавливать.
Я всегда эта картина в виде
Источник: http://www.programcreek.com
, который я видел практически в любом месте, объясняющее класс нагрузку. Если разрешениене достаточно рассматривать как общую ответственность, которая является частью всех этапов, создания/загрузка, проверки, связью и инициализации (с разрешением может быть сделано лениво).
В настоящее время я хотел бы утверждать, что было бы целесообразно принять этап разрешения из этого изображения и объявить его общей процедурой, которая может быть использована в любое время, поскольку информация о других классах может потребоваться на любом этапе, loading такого класса требуется, что обязательно также требует разрешения символической ссылки на этот класс. Из показанного изображения похоже, что разрешение происходит только в определенной точке в цепочке отдельных событий.
Я подозреваю, что это изображение разрешения быть выделенным шагом может быть просто наследство от времени, когда разрешениеникогда не проводились лениво, но имел место, где были решены все остальные символические ссылки.
То, что я хочу знать,: Если разрешениев современных виртуальных машинах следует понимать так, как я описал его?Или я ошибаюсь в этом вопросе, и разрешение все еще может быть понято как выделенный шаг в фиксированной строке времени, как показывает изображение?
Вы считаете, что правы, но определенный ответ может быть получен только при исследовании источников JDK. –
Очень странно. – Mikhail