Оказывается, класс загружается так в практике разработки jvm~|Java.

задняя часть
Оказывается, класс загружается так в практике разработки jvm~|Java.

Это 10-й день моего участия в Gengwen Challenge.Подробности о мероприятии:Обновить вызов

Эта статья участвует в "Java Theme Month - Java Development Practice", подробнее см.Ссылка на мероприятие


Статьи по Теме

Аннотации и размышления Java:Аннотации и отражение Java

предисловие

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

Во-первых, процесс загрузки класса

1. Загрузить

Загрузите содержимое байт-кода файла класса в память, преобразуйте эти статические данные в структуру данных времени выполнения области метода, а затем сгенерируйте объект java.lang.Class, представляющий класс.

2. ссылка

Включите двоичные данные класса в JRE.

  • Проверка: убедитесь, что загруженная информация о классе соответствует спецификации JVM и что нет проблем с безопасностью.
  • Подготовка: Этап формального выделения памяти для переменных класса (статических) и установки начального значения переменных класса по умолчанию, эта память будет выделена в области методов
  • Решение: процесс замены символической ссылки (имя константы) пула констант виртуальной машины на прямую ссылку (адрес).
3. Инициализировать: виртуальная машина JVM отвечает за инициализацию класса.
  • Процесс выполнения метода конструктора класса(). Метод конструктора класса () создается комбинацией действий присваивания и операторов в статических блоках кода, которые автоматически собирают все переменные класса в классе во время компиляции. (Конструктор класса предназначен для создания информации о классе, а не для создания объектов этого класса)
  • При инициализации класса, если обнаруживается, что его родительский класс не был инициализирован, необходимо сначала начать инициализацию своего родительского класса.
  • Виртуальная машина обеспечивает правильную блокировку и синхронизацию метода класса () в многопоточной среде.

Схема выглядит следующим образом:在这里插入图片描述Тестовый код:

public class test01 {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(A.num);
    }
}
class A{
    static {
        System.out.println("静态代码块初始化!");
        num = 500;
    }
    static Integer num = 100;
    public A(){
        System.out.println("无参构造初始化!");
    }

}

Результат выполнения следующий:在这里插入图片描述

в заключении:

①Сначала выполните блок статического кода, затем присвойте 500 номеру

② Затем выполните конструктор без аргументов, который на самом деле является нашей новой операцией.

③Выполнить число = 100;

④Вы можете просто получить последовательность загрузки классов!

Во-вторых, инициализация класса

Код преамбулы:

public class test01 {
    static {
        System.out.println("我是main类的静态代码块。main类被加载啦~");
    }
    public static void main(String[] args) {
        
    }
}
class A{
    static int b = 2;
    static {
        System.out.println("父类A被加载~");
    }
}
class B extends A{
    static {
        System.out.println("子类B被加载~");
        b = 500;
    }
    static int m = 100;
    static final int M = 1;
}

Этот вопрос можно обсудить в двух случаях: 1. Активная ссылка класса (должна произойти инициализация класса)

  • При запуске виртуальной машины сначала инициализируйте класс, в котором находится основной метод.
  • НОВЫЙ объект класса
  • вызовите статические элементы (кроме окончательных констант) и статическими методами класса
  • Используйте методы пакета java.lang.reflect для вызовов рефлексии для классов.
  • При инициализации класса, если его родительский класс не был инициализирован, его родительский класс будет инициализирован первым
public static void main(String[] args) {
		//主动引用
        B b = new B();
    }

результат:在这里插入图片描述

public static void main(String[] args) {
		//反射也会产生主动引用
       Class.forName("com.dbright.Test.B");
    }

在这里插入图片描述

2. Пассивные ссылки на классы (инициализация класса не происходит)

  • При доступе к статическому полю будет инициализирован только класс, который фактически объявляет поле.Например, когда на статическую переменную родительского класса ссылаются через подкласс, подкласс не будет инициализирован.
  • Определение ссылки на класс через массив не вызывает инициализацию этого класса
  • Ссылочные константы не запускают инициализацию этого класса (константы сохраняются в пуле констант вызывающего класса на этапе связывания)
public static void main(String[] args) {
		//调用父类静态变量
      System.out.println(B.b);
    }

在这里插入图片描述

public static void main(String[] args) {
		//定义自身数组
      B[] array = new B[5]; 
    }

在这里插入图片描述

public static void main(String[] args) {
		//调用自身静态变量
      System.out.println(B.M);
    }

在这里插入图片描述

В-третьих, загрузчик классов

загрузчик классовэффект: загрузить содержимое байт-кода файла класса в память, преобразовать эти статические данные в структуру данных времени выполнения области методов, а затем сгенерировать объект java.lang.Class, представляющий этот класс в куче в качестве данных в доступе к области методов. Вход. Загрузчики классов в основном делятся на три уровня:

  • Загрузчик классов Bootstrap:Написанный на C++, это загрузчик классов, поставляемый с JVM, который отвечает за основную библиотеку платформы Java и используется для загрузки основной библиотеки классов. Загрузчик не может напрямую получить Java\jdk1.8\jre\lib\rt.jar
  • Загрузчик класса расширения:Отвечает за упаковку пакета jar в каталоге jre/lib/ext или пакета jar в каталоге, указанном параметром -D java.ext.dirs, в рабочую библиотеку.
  • Загрузчик системного класса:Отвечает за упаковку классов и jar-файлов в каталог, на который указывает java -classpath или -D java.class.path, и является наиболее часто используемым загрузчиком.

Кэш класса:Стандартный загрузчик классов JavaSE может находить классы по запросу, но как только класс загружается в загрузчик классов, он остается загруженным (кэшируется) в течение определенного периода времени, но механизм сборки мусора JVM может повторно использовать эти объекты класса.

public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取系统类的加载器
        ClassLoader loader = ClassLoader.getSystemClassLoader();
        System.out.println(loader);  //sun.misc.Launcher$AppClassLoader@18b4aac2

        //获取系统类加载的父类加载器-->扩展类加载器
        ClassLoader parent = loader.getParent();
        System.out.println(parent);  //sun.misc.Launcher$ExtClassLoader@74a14482

        //获取扩展类加载器的父类加载器-->根加载器(C/C++)
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);  //null

        //测试当前类是哪个加载器加载的
        ClassLoader classLoader = Class.forName("com.dbright.Test.Test02").getClassLoader();
        System.out.println(classLoader);  //sun.misc.Launcher$AppClassLoader@18b4aac2

        //测试JDK内部类是谁加载的
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);  //null

        // 如何获取系统类加载器可以加载的路径
        System.out.println(System.getProperty("java.class.path"));
        /*
        D:\Software\Java\jdk1.8\jre\lib\charsets.jar;
        D:\Software\Java\jdk1.8\jre\lib\deploy.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\access-bridge-64.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\cldrdata.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\dnsns.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\jaccess.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\jfxrt.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\localedata.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\nashorn.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\sunec.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\sunjce_provider.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\sunmscapi.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\sunpkcs11.jar;
        D:\Software\Java\jdk1.8\jre\lib\ext\zipfs.jar;
        D:\Software\Java\jdk1.8\jre\lib\javaws.jar;
        D:\Software\Java\jdk1.8\jre\lib\jce.jar;
        D:\Software\Java\jdk1.8\jre\lib\jfr.jar;
        D:\Software\Java\jdk1.8\jre\lib\jfxswt.jar;
        D:\Software\Java\jdk1.8\jre\lib\jsse.jar;
        D:\Software\Java\jdk1.8\jre\lib\management-agent.jar;
        D:\Software\Java\jdk1.8\jre\lib\plugin.jar;
        D:\Software\Java\jdk1.8\jre\lib\resources.jar;
        D:\Software\Java\jdk1.8\jre\lib\rt.jar;
        D:\NEU\learn\java\project\out\production\project;
        D:\NEU\learn\java\project\src\com\lib\commons-io-2.8.0.jar;
        D:\Software\IntelliJ IDEA 2020.1.4\lib\idea_rt.jar
         */
        //双亲委派机制:如果上层加载器存在不会使用下层定义类
    }
}

在这里插入图片描述 Механизм родительского делегирования: если существует загрузчик верхнего уровня, класс определения нижнего уровня не будет использоваться.


Впереди долгий путь, и я обязательно буду его искать вдоль и поперёк~

Если вы думаете, что я блогеры хорошо пишу! Писать нелегко, пожалуйста, ставьте лайки, подписывайтесь и комментируйте, чтобы поощрять блоггеров ~ хахах