Автор: No Dishwashing Studio - Marklux
Источник:Marklux's Pub
Все права принадлежат автору, при перепечатке указывать источник
Эта часть организована из «Глубокого понимания виртуальной машины JVM».
Жизненный цикл класса и время загрузки
-
жизненный цикл класса
Класс начинается с загрузки в память виртуальной машины и заканчивается выгрузкой из памяти Весь жизненный цикл включает 7 этапов загрузки, проверки, подготовки, парсинга, инициализации, использования и выгрузки. Три части проверки, подготовки и анализа вместе называются ссылками, как показано на следующем рисунке:
Вся последовательность не является полностью фиксированной, в которой фаза синтаксического анализа может начаться после инициализации, чтобы можно было реализовать механизм привязки Java во время выполнения (динамическая привязка).
-
время загрузки класса
Спецификация виртуальной машины JVM не предъявляет строгих требований к времени загрузки классов, а лишь оговаривает следующие пять ситуаций, в которых необходимо немедленно инициировать инициализацию класса:
- При встрече с четырьмя инструкциями байт-кода new, getstatic, putstatic и invokestatic, если класс не был инициализирован, его инициализация должна быть запущена в первую очередь.
- При использовании механизма отражения для вызова класса, если класс не был инициализирован, вам необходимо сначала запустить его инициализацию.
- При инициализации класса, если его родительский класс не был инициализирован, он должен сначала инициировать инициализацию своего родительского класса.
- При запуске виртуальной машины пользователю необходимо указать основной класс (включая основной метод), который будет выполняться, и этот класс будет инициализирован первым.
- При использовании динамической языковой поддержки JDK1.7, если
MethodHandle
Окончательный результат синтаксического анализа экземпляра содержитREF_getStatic
,REF_putStatic
,REF_invokeStatic
Дескриптор метода и класс, соответствующий этому дескриптору метода, не инициализируются, его необходимо сначала инициализировать.
При других условиях виртуальная машина JVM сама решает, когда загружать класс.
-
Активные и пассивные цитаты
Вышеуказанные пять условий также известны как специфичные для класса.Активное цитирование, другие способы ссылки на класс не вызовут инициализацию, т.пассивное цитирование,Например:
public class Father { static { System.out.println("father init."); } public static int val = 123; } public class Son extends Father { static { System.out.println("son init."); } }
когда мы посещаем
Son.val
, вы обнаружите, что выхода нетson init.
Для статических полей будет инициализирован только класс, который непосредственно определяет поле, поэтому для обращения к статическому полю родительского класса через подкласс подкласс эквивалентен пассивной ссылке, и он не будет инициализирован.
процесс загрузки класса
Ниже кратко показано, что JVM выполняет на каждом этапе в течение всего процесса загрузки:
Загрузка
Процесс загрузки является основной особенностью Java, а источники классов могут быть разнообразными, такими как сжатые пакеты, сетевые потоки байтов, генерация динамических вычислений во время выполнения (рефлекс) и т. д. Это также создает мощные динамические характеристики языка Java.
- Получите двоичный поток байтов, определяющий этот класс по его полному имени (обратите внимание, что источник потока байтов очень гибкий)
- Преобразуйте статическую структуру хранения, представленную этим потоком байтов, в структуру данных времени выполнения области метода.
- Генерирует представление этого класса в памяти
java.lang.Class
Объект, как запись доступа к различным данным этого класса в области методов
Проверка
Этот процесс в основном предназначен для обеспечения того, чтобы информация, содержащаяся в потоке байтов класса, соответствовала стандарту виртуальной машины, чтобы не нанести ущерб
- проверка формата файла
- проверка метаданных
- Проверка байт-кода посредством анализа потока данных и потока управления, чтобы определить, является ли семантика программы законной.
- Проверка символьной ссылки, чтобы убедиться, что действие разрешения может быть выполнено нормально
Подготовка
На этом этапе будет выделена память для переменных класса и установлены их начальные значения.Обратите внимание, что в это время для памяти выделяются только переменные класса (статическая модификация), и начальным значением обычно является нулевое значение типа данных вместо установленного значения. Следующий пример
public static int val = 123;
Переменные на этом этапеval
Присвоение равно 0 вместо 123, потому что в этот момент ни один метод Java не выполнялся, иval
копироватьputstatic
Инструкции не выполняются до завершения фазы инициализации.
Конечно, есть частные случаи, как показано ниже.
public static final int val = 123;
После добавления окончательной модификации ключевого слова время компиляции Java будетval
генерироватьConstantValue
свойство, то на этапе подготовки для него будет установлено значение 123 в соответствии с настройками.
разрешение
На этом этапе виртуальная машина заменяет символы в константном пуле прямыми ссылками, которые в основном включают следующие действия:
- Класс или разрешение интерфейса
- разбор поля
- разбор метода класса
- Анализ метода интерфейса
Инициализация
В это время последний шаг процесса загрузки класса, эта часть запускает реальное выполнение кода Java, то есть на этом этапе может участвовать программист.
Эта фаза фактически является выполнением конструктора класса.<clinit>()
процесс метода.
загрузчик классов
Загрузчик классов (Class Loader) — отличное новшество виртуальной машины Java. Он оставляет процесс «получения бинарного байтового потока класса» на усмотрение самих разработчиков. Пока пишутся разные Загрузчики классов, само приложение может использовать соответствующий метод для получения нужного вам класса.
Связь между классами и загрузчиками
Для любого класса его уникальность в виртуальной машине должна быть установлена загружающим его загрузчиком классов и самим классом.
С точки зрения непрофессионала, даже если один и тот же файл класса загружается разными загрузчиками классов, он не получит один и тот же «класс» (метод equals возвращает false).
Модель родительского делегирования
С точки зрения виртуальной машины есть только два загрузчика классов, один — это Bootstrap ClassLoader, который реализован на C++ в hotpot и является частью виртуальной машины; другой — загрузчик для всех остальных классов, эти загрузчик не зависит от виртуальной машины и реализуется языком Java.С точки зрения разработчика его можно разделить на следующие две категории:
-
Расширение ClassLoader
-
Загрузчик классов приложений
Конечно, разработчики также могут написать свои собственные загрузчики классов.Окончательная иерархическая взаимосвязь между различными загрузчиками классов показана на следующем рисунке:
Это то, что известно в JavaМодель родительского делегирования, который требует, чтобы все загрузчики классов, кроме загрузчика BootStrap верхнего уровня, имели загрузчик родительских классов. Рабочий процесс выглядит следующим образом:
Если загрузчик класса получает запрос на загрузку класса, он не будет пытаться загрузить класс сам по себе, а делегирует запрос загрузчику родительского класса для завершения, только когда родительский загрузчик сообщает, что он не может выполнить запрос на загрузку. попробуйте загрузить класс сам по себе.
Преимущество этого в том, что класс Java имеет иерархию приоритетов вместе с загрузчиком классов. Например, какjava.lang.Object
Этот класс, независимо от того, какой загрузчик классов загружен, в конечном итоге будет делегирован для загрузки загрузчику Bootstrap, что гарантирует, что вся система работает.Object
все одного класса.
В противном случае, если пользователь написалjava.lang.Object
class и поместите его в путь к классам программы.В конце концов, в системе будет несколько разных классов Object, и вся система Java превратится в беспорядок.