Подробный и полный процесс создания объектов

Java
Подробный и полный процесс создания объектов

Что должен делать процесс создания экземпляра объекта? Во-первых, Java — объектно-ориентированный язык, класс — это абстракция всех объектов, принадлежащих классу, вся структурная информация объекта определяется в классе, поэтому создание объекта должно основываться на информация о типе, определенная в классе, а также это поток двоичных байтов класса, соответствующий классу, поэтому это включает в себя загрузку и инициализацию класса. Во-вторых, объекты в основном хранятся в куче памяти, что требует выделения памяти. Кроме того, есть также инициализированные нулевые значения переменных, установка заголовков объектов, ссылки на объекты, созданные в стеке и т. д. В этой статье мы подробно разберем полный процесс инстанцирования объектов.

1 Общий процесс

Весь процесс инстанцирования объекта с точки зрения целого дня показан на следующем рисунке:

Для плавного развития истории здесь мы определяем демонстрацию и подробно обсуждаем, как создается и реализуется объект постоянного тока.

public class Demo
{

    public static void main(String[] args)
    {
        DemoClass dc=new DemoClass();
    }
}
class DemoClass
{
    private static final int a=1;
    private static int b=2;
    private static int c;
    private int d=4;
    private int e;
    static
    {
        c=3;
    }
    public DemoClass()
    {
        e=5;
    }

}

2 проверки инициализации класса

Здесь мы используем новое ключевое слово для создания объектов.Существует множество способов создания объектов в Java, таких как отражение, клонирование, сериализация и десериализация и т. д. Эти методы различны, но после компиляции компилятором он соответствует новой инструкции в виртуальной машине Java (здесь новая инструкция отличается от упомянутого выше нового ключевого слова, которое является инструкцией уровня виртуальной машины). Когда виртуальная машина Java встречает новую инструкцию, она сначала обращается к пулу констант, чтобы узнать, существует ли ссылка на символ, соответствующая классу в соответствии с параметрами, соответствующими инструкции, и определить, был ли класс загружен, проанализирован , и инициализировать.То есть перейти в область методов, чтобы проверить, есть ли информация о типе класса, если нет, во-первых, загрузить и инициализировать класс. Если класс уже загружен и инициализирован, продолжите последующие операции.

Здесь предполагается, что класс DemoClass не загружен и не инициализирован, то есть в области методов нет информации о типе DemoClass, в это время класс DemoClass необходимо загрузить и инициализировать.

Процесс загрузки 3 класса

Процесс загрузки класса можно разделить на 7 шагов: загрузка, проверка, подготовка, синтаксический анализ, инициализация, использование и выгрузка. Здесь мы рассмотрим первые шесть этапов.

нагрузка

Фаза загрузки в основном делает три вещи:

  1. Получает поток двоичных байтов для класса на основе его полного имени.

  2. Преобразуйте статическую структуру хранения, представленную двоичным потоком байтов, в структуру данных времени выполнения в области методов.

  3. Создайте объект Java.lang.Class, представляющий класс в памяти как запись доступа к различным данным этого класса в области методов.

В частности, сначала нужно найти двоичный файл DemoClass.class в соответствии с полным именем package.DemoClass, затем загрузить файл .class в память для синтаксического анализа, сохранить проанализированный результат в области методов и, наконец, создать файл в память кучи Объект Java.lang.Class используется для доступа к информации о классе, загруженной в область методов.

проверять

Основная задача этапа проверки - убедиться, что информация, содержащаяся в потоке байтов в файле класса, соответствует спецификациям виртуальной машины Java.Хотя это очень просто, виртуальная машина Java выполнила много сложных проверок работу, которую можно разделить в целом на четыре аспекта:

  • проверка формата файла

  • проверка метаданных

  • Проверка байт-кода

  • Проверка символьной ссылки

    В частности, информация, хранящаяся в классе DemoClass.class, загруженном в память, проверяется на уровне виртуальной машины, чтобы гарантировать, что информация, хранящаяся в классе DemoClass.class, не поставит под угрозу работу виртуальной машины Java.

Подготовить

Работа, выполняемая на этапе подготовки, заключается в выделении памяти для переменных класса (то есть статических переменных) и присвоении начальных значений, обычно нулевого значения типа данных, соответствующего переменной. Но на данном этапе переменные, которые модифицируются final, то есть константы, будут назначаться точно на этом этапе.

В частности, на этом этапе a в DemoClass будет присвоено значение 1, а b и c будут присвоены значения 0.

Разобрать

Основная задача на данном этапе — замена символьных ссылок в константном пуле прямыми ссылками.

инициализация

На предыдущем этапе, за исключением того, что этап загрузки может вмешиваться в процесс загрузки виртуальной машины через пользовательский загрузчик классов, на других этапах полностью доминирует виртуальная машина, а этап инициализации начинает выполнять класс в соответствии с пожелания программиста.Инициализация, основная работа, выполняемая на этом этапе, заключается в выполнении метода конструктора класса (), и виртуальная машина обеспечивает, чтобы при выполнении метода конструктора класса класса, метод конструктора класса его родительского класса имел была выполнена правильно. Инициализация выполняется только один раз. Когда несколько потоков инициализируются одновременно, виртуальная машина может гарантировать, что только один из нескольких потоков может завершить инициализацию класса, обеспечивая поточно-безопасную работу.

Для класса DemoClass на этом этапе b будет присвоено значение 2, а c будет присвоено значение 3.

4 Выделение памяти

Когда процесс загрузки класса завершен или сам класс был загружен ранее, следующим шагом виртуальной машины является выделение памяти для нового объекта. Объем памяти, необходимый объекту, может быть полностью определен после завершения процесса загрузки класса.Выделение памяти для объекта эквивалентно отделению подходящей памяти от памяти кучи.Есть два основных способа выделения памяти: столкновение указателей и свободное список.

  • Коллизия указателя: таким образом память кучи делится на свободное пространство и выделенное пространство, а указатель используется в качестве разделительной линии между ними.Когда пространство памяти выделяется для нового объекта, это эквивалентно указанию указателя на свободное пространство.Переместите расстояние, равное размеру объекта в направлении.Видно, что память кучи Java в этом методе распределения должна быть регулярной, все свободное пространство находится на одной стороне, а выделенное пространство на с другой стороны.

  • Свободный список: в виртуальной машине поддерживается список для записи того, какая часть памяти в куче свободна и доступна.При выделении памяти для нового объекта найдите в списке доступный блок памяти подходящего размера и обновите свободный list после завершения выделения, таким образом, свободное пространство и выделенное пространство кучи памяти могут чередоваться.

  <img src="images/空闲列表.png" style="zoom:80%;" />

С вышеуказанной точки зрения выбор использования метода коллизии указателей или метода свободного списка для выделения памяти в основном определяется тем, является ли память кучи Java регулярной, и является ли память кучи Java регулярной, зависит от используемого алгоритма сборки мусора, который включает механизм сборки мусора (Видно, что знание одно и то же, программист должен жить до старости и научиться умирать!), есть ли действие сжатия или сортировки после GC и т. д.

В то же время, поскольку действие по созданию объектов происходит очень часто, может быть несколько потоков в нескольких потоках, одновременно запрашивающих выделение пространства памяти для объектов.Поток использует исходный указатель для выделения пространства памяти, поэтому есть два решения. производный: CAS в сочетании с повторной попыткой отказа, метод TLAB.

Первый метод хорошо изучен. Несколько потоков используют метод CAS для обновления указателя. При многопоточности только один поток может завершить обновление, а другие потоки завершают удаление указателя памяти, постоянно повторяя попытки.

Второй метод заключается в том, что каждый поток заранее выделяет пространство памяти, которое представляет собой локальный буфер потока TLAB, так что каждый раз, когда потоку необходимо выделить память, он сначала обращается к TLAB для ее получения, а механизм синхронизации используется, когда места в памяти в TLAB недостаточно. Продолжайте применять для части пространства TLAB, что уменьшает количество приложений блокировки синхронизации.

В частности, на этом этапе в памяти кучи открывается пространство памяти для объекта DemoClass, то есть экземпляра объекта dc.

5 Инициализировать нулевое значение

После выделения памяти для объекта виртуальная машина инициализирует выделенную память нулевым значением, так что переменная экземпляра объекта в Java может использоваться без начального значения, потому что доступ к коду Это нулевое значение, выделенное виртуальной машиной для эта память.

В частности, виртуальная машина Java инициализирует пространство памяти, выделенное выше, равным 0. На этом шаге и d, и e в DemoClass теперь присваиваются 0.

6 Установите заголовок объекта

Заголовок объекта — это как бы наша идентификационная карта, в которой хранятся некоторые данные, идентифицирующие объект, то есть некоторые метаданные объекта.Давайте сначала посмотрим на состав объекта.

После инициализации нулевого значения, как узнать, экземпляром какого класса является объект, необходимо установить указатель на информацию о типе в области метода, и на этом установка соответствующей информации в объекте Mark Word завершена. сцена.

7 Инициализация экземпляра объекта

На этом этапе виртуальная машина вызовет метод конструктора экземпляра () для инициализации объекта в соответствии с пожеланиями нашего программиста.На этом этапе будет вызван конструктор для завершения инициализации объекта экземпляра.

В частности, d класса DemoClass присваивается значение 4, а e присваивается значение 5.

8 Создайте ссылку, поместите стек

На данный момент созданный объект уже существует в динамической памяти, но мы знаем, что использование объектов в Java заключается в получении свойств объекта через ссылку в стеке виртуальной машины и вызове методов объекта, поэтому этот шаг создаст объект Ссылка помещается в стек виртуальной машины, и ссылка, наконец, возвращается для нашего использования.

Здесь нужно ввести объект в стек и вернуть присваивание dc, пока объект создан.

Полный поток создания объекта

Основываясь на приведенном выше обсуждении, давайте рассмотрим весь процесс создания экземпляра объекта: