English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Компиляция JAVA-исходного кода состоит из трех процессов:
1. Механизм компиляции исходного кода.
2. Механизм загрузки класса
3. Механизм выполнения класса
Мы здесь основно рассказываем о двух механизмах: компиляции и загрузки класса.
Одна. Компиляция исходного кода
Компиляция кода выполняется компилятором JAVA. В основном это преобразование исходного кода в файл байт-кода (файл class). Формат файла байт-кода主要包括 две части: пул констант и байт-код методов.
Два. Загрузка класса
Жизненный цикл класса начинается с загрузки его в виртуальную память и заканчивается удалением из памяти. Процесс включает семь фаз, все фазы до инициализации относятся к части загрузки класса.
Загрузка----Валидация----Подготовка----Парсинг-----Инициализация----Использование-----Удаление
Система может загружать класс в первый раз при его использовании, или может использовать механизм предварительной загрузки для загрузки класса, при запуске java-программы запускается процесс java-виртуальной машины, два запуска java-программ происходят в двух разных процессах JVM, между двумя JVM данные не共享ятся.
1. Фаза загрузки
Этот процесс загрузки является одной из фаз механизма загрузки класса, эти два концепта не следует путать, в этой фазе необходимо выполнить следующие задачи:
1) Получается двоичный поток байтов класса по полному квалифицированному имени класса.
2) Преобразуется статическая структура хранения двоичного потока в runtime-структуру области методов.
3) В java-пуле создается объект Class, представляющий этот класс, в качестве входа для доступа к этим данным в области методов.
Из-за того, что в первом пункте не указано, откуда и как получить двоичный поток байтов класса, у разработчика есть много места для творчества в этой области. Об этом я расскажу позже в разделе о классовом загрузчике.
2、准备阶段
这个阶段正式为类变量(被static修饰的变量)分配内存并设置类变量初始值,这个内存分配是发生在方法区中。
1、注意这里并没有对实例变量进行内存分配,实例变量将会在对象实例化时随着对象一起分配在JAVA堆中。
2、这里设置的初始值,通常是指数据类型的零值。
private static int a = 3;
这个类变量a在准备阶段后的值是0,将3赋值给变量a是发生在初始化阶段。
3、初始化阶段
初始化是类加载机制的最后一步,这个时候才正真开始执行类中定义的JAVA程序代码。在前面准备阶段,类变量已经赋过一次系统要求的初始值,在初始化阶段最重要的事情就是对类变量进行初始化,关注的重点是父子类之间各类资源初始化的顺序。
java类中对类变量指定初始值有两种方式:1、声明类变量时指定初始值;2、使用静态初始化块为类变量指定初始值。
初始化的时机
1)创建类实例的时候,分别有:1、使用new关键字创建实例;2、通过反射创建实例;3、通过反序列化方式创建实例。
new Test(); Class.forName("com.mengdd.Test");
2)调用某个类的类方法(静态方法)
Test.doSomething();
3)访问某个类或接口的类变量,或为该类变量赋值。
int b=Test.a; Test.a=b;
4)初始化某个类的子类。当初始化子类的时候,该子类的所有父类都会被初始化。
5)直接使用java.exe命令来运行某个主类。
除了上面几种方式会自动初始化一个类,其他访问类的方式都称不会触发类的初始化,称为被动引用。
1、子类引用父类的静态变量,不会导致子类初始化。
public class SupClass { public static int a = 123; static { System.out.println("supclass init"); } } public class SubClass extends SupClass { static { System.out.println("subclass init"); } } public class Test { public static void main(String[] args) { System.out.println(SubClass.a); } }
Результат выполнения:
supclass init
123
2、通过数组定义引用类,不会触发此类的初始化
public class SupClass { public static int a = 123; static { System.out.println("supclass init"); } } public class Test { public static void main(String[] args) { SupClass[] spc = new SupClass[10]; } }
Результат выполнения:
3. При использовании ссылки на константу не будет инициирован инициализация этого класса
public class ConstClass { public static final String A= "MIGU"; static { System.out.println("ConstCLass init"); } } public class TestMain { public static void main(String[] args) { System.out.println(ConstClass.A); } }
Результат выполнения:
MIGU
При использовании final для определенного классового переменной, его значение уже определено в компиляции и поместлено в пул констант, поэтому при доступе к этой переменной равно напрямую получить из пула констант, не initializing этот класс.
Шаги инициализации
1. Если класс еще не загружен и не свяжен, программа сначала загружает этот класс и связывает его.
2. Если прямой родительский класс этого класса не загружен, сначала инициализируется его прямой родительский класс.
3. Если в классе есть инициализационные инструкции, система выполняет их по порядку.
Во втором шаге, если у прямого родительского класса又有 прямой родительский класс, система повторно повторит эти три шага для инициализации этого родительского класса, и так далее, JVM в первую очередь инициализирует класс java.lang.Object. При активном использовании любого класса системой гарантируется, что будет инициализирован этот класс и все его родительские классы.
Названное выше - это介绍JAVA загрузчик классов (рекомендуется) от редактора, который надеется помочь вам!
Объявление: содержание этой статьи предоставлено из Интернета, авторские права принадлежат соответствующему владельцу, контент был предложен и загружен пользователями Интернета, сайт не имеет права собственности, не underwent редактирование, и не несет ответственности за соответствующие юридические последствия. Если вы обнаружите содержимое,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма, пожалуйста, замените # на @) для сообщения о нарушении,并提供 соответствующие доказательства. При подтверждении, сайт немедленно удалят涉嫌侵权的内容.