написать впереди
Невозможно описать сложность механизма загрузки классов Java. Потому что, когда я изучал этот контент, я был более или менее сбит с толку, поэтому в этой статье я попытаюсь преобразовать концептуальные вещи в простой для понимания контент, поэтому я надеюсь, что вы сможете прочитать статью.
#начало текста
Во-первых, давайте посмотрим на кусок кода:
public class Main {
static{
System.out.println("我是静态代码块");
}
{
System.out.println("我是实例代码块");
}
public static void main(String[] args) {
Main main1=new Main();
Main main2=new Main();
}
}
Дорогие друзья, а как будет выглядеть этот код после запуска? Я не буду продавать его здесь, просто опубликую результаты напрямую.
Хорошо, если вы, ребята, знаете этот результат и понимаете его, вы можете пропустить следующий контент. Если вы сомневаетесь, давайте возьмем этот ответ и посмотрим вниз, с очень небольшим содержанием. Важно понять~
Механизм загрузки классов Java
первый взгляд на концепт
Виртуальная машина загружает данные, описывающие класс, из файла класса в память, проверяет, преобразует, анализирует и инициализирует данные и, наконец, формирует тип Java, который может быть непосредственно использован виртуальной машиной.Это механизм загрузки класса. виртуальной машины. (Источник «Углубленное понимание виртуальной машины Java. Второе издание», именуемое в дальнейшем «Углубленное понимание JVM»)
Концепция всегда скучна, давайте начнем анализировать и комбинировать эту концепцию.
гребень
1. Загрузить
прежде всегонагрузкаЭтап: на этом этапе Java считывает данные байт-кода (файл .class) из разных источников данных (наши jar-файлы, файлы классов, даже сетевые источники данных и т. д., если структура верна) в JVM и сопоставляется с структура данных, одобренная JVM (объект класса, понятным достижением является java.lang.Class). Согласно описанию «Углубленная JVM», этот процесс состоит из трех шагов (с обработкой некоторых слов):
- 1. Получите поток двоичных байтов, определяющий этот класс, через полное имя класса. (то есть сначала найти .class файл этого класса по пути)
- 2. Преобразуйте структуру кода, представленную потоком байтов .class, в структуру данных среды выполнения области методов. (Можно понять, что в настоящее время это стало распознаваемой структурой кода в виртуальной машине)
- 3. Создайте объект java.lang.Class, который может представлять этот класс в памяти как запись для различных данных этого класса в области методов. (Здесь это очень сложно понять. Насколько я понимаю, хотя структура кода уже существует, у нас нет возможности использовать ее напрямую. Поэтому объект java.lang.Class здесь абстрагируется как интерфейс для байт-кода файл .class. )
Здесь у меня были некоторые сомнения по поводу байт-кода и двоичных файлов. На самом деле все они являются файлами .class.Давайте просто скомпилируем приведенный выше файл Main.java.
Сначала мы переходим в каталог, где находится Main, компилируем и просматриваем байт-код .class.
Советы:нагрузкаНа этом этапе мы можем настроить загрузчик классов для реализации нашего собственного процесса загрузки классов.
2. Подключение
Процессы подключения и загрузки чередуются, что означает, что фаза подключения может уже начаться до завершения фазы загрузки.
Второй этапсоединять, это основной шаг, короче говоря, исходная информация об определении класса плавно трансформируется в процесс работы JVM. Далее его можно разделить на три этапа:
- 1,проверять: это важная гарантия безопасности виртуальной машины. JVM необходимо проверить, соответствует ли информация о байтах спецификации виртуальной машины Java. Фаза проверки может инициировать загрузку большего количества классов.
- 2,Подготовить: Создайте статическую переменную в классе или интерфейсе и инициализируйте начальное значение статической переменной.Основное внимание при инициализации здесь уделяется выделению необходимого пространства памяти, и никакого присвоения не производится., то есть инициализированное значение здесь является значением по умолчанию, таким как
public static int value = 666, значение в это время равно 0, а не 666. И настоящая операция присваивания находится винициализациясцена. - 3.Разобрать: этот шаг заменит символическую ссылку в пуле констант прямой ссылкой. Этот короткий текст я понял давно, потому что он содержит много понятий: константные пулы, символические ссылки, прямые ссылки. Ниже приводится объяснение по одному:
постоянный пул: В дополнение к объектам String, константам конечного типа иСимволическая ссылка.Символическая ссылка: используется для описания полей, методов, интерфейсов и т. д. в файле байт-кода. Вот как я это понимаю: если поля и методы все воображаемые туристы, которые хотят путешествовать, то символическим ориентиром является турфирма, но турфирма несет ответственность только за сбор денег для организации туристов, на самом деле они не несут ответственности водить туристов играть, на самом деле водить их играть в качестве гида (прямая цитата). то естьСимволическая ссылкаИменно такая роль может представлять все поля и методы.прямая цитата: Прямая ссылка приходит на роль возможности найти соответствующий адрес памяти, который является путеводителем в приведенном выше примере.
PS: я не знаю, смогу ли я понять это объяснениеРазобратьЕсли вы все еще в замешательстве, вы можете проверить профессиональный ответ Чжиху на этот вопрос: https://www.zhihu.com/question/30300585.
3. Инициализация
Ну наконец тоинициализацияЭтап, этот шаг начинает выполнять действие статического назначения поля, логика в статическом блоке инициализации, компилятор отсортировал логику кода, которая будет выполняться на этапе компиляции, здесь следует отметить: логика инициализации родителя класс имеет приоритет над логикой класса дочернего класса.
Здесь здесь есть одна деталь: только переменные, определенные до доступа к блоку статического кода в статическом блоке кода. Если эта статическая переменная находится за статическим блоком кода, он может быть назначен только значение в блоке статического кода и не может быть доступен:
конец загрузки
Здесь наш класс официально загружается, а также генерируется соответствующий объект класса.Но обратите внимание, Здесь не задействована инстанцирование класса, то есть новая операция еще не началась.
При выполнении new и загрузке класса будет выполнена соответствующая реализация, например выделение памяти, выполнение блоков кода, построение методов и т. д. (если есть родительский класс, они должны быть выполнены в первую очередь).
Действие, запускающее загрузку класса
- новое ключевое слово; получить/установить статическую переменную (за исключением финальных статических полей, которые входят в пул констант во время компиляции); вызвать статические методы.
- Используя отражение, класс будет загружен первым, если он не загружен.
- Класс, соответствующий основному методу, будет загружен при запуске JVM.
- При использовании некоторых методов динамического прокси.
Механизм родительского делегирования
Что касается механизма родительского делегирования, статья MDove проста и понятна, но на самом деле это картинка:
Говоря словами «В JVM», объясните: Рабочий процесс модели родительского делегирования: если загрузчик класса получает запрос на загрузку класса, он не будет пытаться загрузить класс сам по себе, а делегирует запрос загрузчику родительского класса для завершения, каждый уровень загрузчиков классов такой . Таким образом, все запросы на загрузку в конечном итоге должны быть отправлены загрузчику класса запуска верхнего уровня.Только когда родительский загрузчик сообщает, что он не может выполнить запрос на загрузку, дочерний загрузчик попытается загрузить его самостоятельно.
конец
На этом разбор загрузки классов закончился, интересно, ребята, вы это понимаете? Если у друзей есть свое понимание или в тексте есть что-то неуместное, пожалуйста, оставьте сообщение в области комментариев ~ Поздравляем!