- PVSM.RU - https://www.pvsm.ru -
Перевод статьи подготовлен специально для студентов курса «Разработчик Java» [1].
Виртуальная машина Java — это сердце экосистемы Java-технологий. Она делает для Java-программ возможность реализации принципа «написано один раз, работает везде» (write once run everywhere). Как и другие виртуальные машины, JVM представляет собой абстрактный компьютер. Основная задача JVM — загружать class-файлы [3] и выполнять содержащийся в них байт-код [4].
В состав JVM входят различные компоненты, такие как загрузчик классов (Classloader) [5], сборщик мусора (Garbage Collector) [6] (автоматическое управление памятью), интерпретатор, JIT [7]-компилятор, компоненты управления потоками. В этой статье рассмотрим загрузчик классов (Class loader).
Загрузчик классов загружает class-файлы как для вашего приложения, так и для Java API. В виртуальную машину загружаются только те class-файлы Java API, которые действительно требуются при выполнении программы.
Байт-код выполняется подсистемой исполнения (execution engine).
Загрузка классов [8] — это поиск и загрузка типов (классов и интерфейсов) динамически во время выполнения программы. Данные о типах находятся в бинарных class-файлах.
Подсистема загрузчика классов отвечает не только за поиск и импорт бинарных данных класса. Она также выполняет проверку правильности импортируемых классов, выделяет и инициализирует память для переменных класса, помогает в разрешении символьных ссылок. Эти действия выполняются в следующем порядке:
Примечание — загрузчик классов, помимо загрузки классов, также отвечает за поиск ресурсов. Ресурс — это некоторые данные (например, “.class” файл, данные конфигурации, изображения), которые идентифицируются с помощью абстрактного пути, разделенного символом «/». Ресурсы обычно упаковываются вместе с приложением или библиотекой для того, чтобы их можно было использовать в коде приложения или библиотеки.
Примечание переводчика — в данном разделе описано поведение для java < 9, в java 9+ произошли небольшие изменения, которые описаны ниже.
В Java используется модель делегирования загрузки классов. Основная идея состоит в том, что у каждого загрузчика классов есть “родительский” загрузчик. Когда происходит загрузка класса [8], то загрузчик “делегирует” поиск класса своему родителю, перед тем как искать класс самостоятельно.
Модель делегирования загрузчиков классов представляет собой граф загрузчиков, которые передают друг другу запросы на загрузку. Корнем в этом графе является bootstrap-загрузчик. Загрузчики классов создаются с одним родителем, которому они могут делегировать загрузку, и осуществляют поиск класса в следующих местах:
Загрузчик классов сначала проверяет, не загружал ли он данный класс ранее. Если это так, то возвращается тот же класс, который возвращался в прошлый раз (класс, хранящийся в кэше). Если нет, то возможность загрузить класс предоставляется родителю. Эти два шага повторяются рекурсивно в глубину. Если родитель возвращает null (или бросает исключение ClassNotFoundException [9]), тогда загрузчик ищет класс самостоятельно.
Класс загружается тем загрузчиком, который ближе всего к корню, поскольку право первому загрузить класс всегда предоставляется загрузчику-родителю. Это позволяет загрузчику видеть только классы, загруженные самостоятельно, его родителем или предками. Он не может видеть классы, загруженные дочерними загрузчиками.
В Java SE Platform API исторически было определено два загрузчика классов:
Bootstrap class loader (базовый, первичный загрузчик) — загружает классы из bootstrap classpath.
System class loader (системный загрузчик) — родительский класс для новых загрузчиков классов и, как правило, загрузчик классов, используемый для загрузки и запуска приложения.
Application class loader — обычно используется для загрузки классов приложения из classpath. Также это загрузчик по умолчанию для некоторых модулей JDK, которые содержат утилиты или экспортируют API утилит. (Примечание переводчика: например, jdk.jconsole
, jdk.jshell
и др)
Platform class loader — загружает выбранные (на основе безопасности / разрешений) модули Java SE и JDK. Например, java.sql.
Bootstrap class loader — загружает основные модули Java SE и JDK.
Эти три встроенных загрузчика классов работают вместе следующим образом:
Для просмотра встроенных загрузчиков классов можно использовать следующий код:
package ru.deft.homework;
import java.sql.Date;
public class BuiltInClassLoadersDemo {
public static void main(String[] args) {
BuiltInClassLoadersDemo demoObject = new BuiltInClassLoadersDemo();
ClassLoader applicationClassLoader = demoObject.getClass().getClassLoader();
printClassLoaderDetails(applicationClassLoader);
// java.sql classes are loaded by platform classloader
java.sql.Date now = new Date(System.currentTimeMillis());
ClassLoader platformClassLoder = now.getClass().getClassLoader();
printClassLoaderDetails(platformClassLoder);
// java.lang classes are loaded by bootstrap classloader
ClassLoader bootstrapClassLoder = args.getClass().getClassLoader();
printClassLoaderDetails(bootstrapClassLoder);
}
private static void printClassLoaderDetails(ClassLoader classLoader) {
// bootstrap classloader is represented by null in JVM
if (classLoader != null) {
System.out.println("ClassLoader name : " + classLoader.getName());
System.out.println("ClassLoader class : " + classLoader.getClass().getName());
} else {
System.out.println("Bootstrap classloader");
}
}
}
Запустив этот код на установленном у меня Amazon Corretto 11.0.3, получим следующий результат:
ClassLoader name : app
ClassLoader class : jdk.internal.loader.ClassLoaders$AppClassLoader
ClassLoader name : platform
ClassLoader class : jdk.internal.loader.ClassLoaders$PlatformClassLoader
Bootstrap classloader
Подробнее изучить ClassLoader API вы можете здесь (JDK 11) [10].
Автор: MaxRokatansky
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/java/330734
Ссылки в тексте:
[1] «Разработчик Java»: https://otus.pw/9Skf/
[2] JVM: https://javarevisited.blogspot.com/2011/12/jre-jvm-jdk-jit-in-java-programming.html
[3] class-файлы: https://en.wikipedia.org/wiki/Java_class_file
[4] байт-код: https://en.wikipedia.org/wiki/Java_bytecode
[5] загрузчик классов (Classloader): https://javarevisited.blogspot.com/2012/12/how-classloader-works-in-java.html#axzz5Y4KhSOWu
[6] сборщик мусора (Garbage Collector): https://javarevisited.blogspot.com/2011/04/garbage-collection-in-java.html#axzz4zt6jlTWS
[7] JIT: http://javarevisited.blogspot.sg/2011/12/jre-jvm-jdk-jit-in-java-programming.html
[8] Загрузка классов: http://javarevisited.blogspot.sg/2012/07/when-class-loading-initialization-java-example.html#axzz4uMIMWleJ
[9] ClassNotFoundException: https://javarevisited.blogspot.com/2013/01/spring-javalangclassnotfoundexception-springframeworkwebcontextloaderlistener.html
[10] здесь (JDK 11): https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ClassLoader.html
[11] Источник: https://habr.com/ru/post/468193/?utm_campaign=468193&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.