Предисловие
Каждый должен знать, что когда запускается проект Java, JVM найдет основной метод и загрузит файл класса и файл класса в упоминаемом пакете JAR в соответствии с вызовами между объектами (шаги разделены на загрузку, проверку, подготовку, анализ, инициализацию, использование и разгрузка). Область метода открывает память для хранения структуры данных времени выполнения класса (включая статические переменные, статические методы, постоянные пулы, структуры класса и т. Д.), И в то же время соответствующий объект класса генерируется в куче, чтобы указывать на соответствующую структуру данных выполнения класса в области метода.
Подводя итог в простейшем предложении, процесс загрузки класса заключается в том, что JVM считывает файл байт -кода класса через потоки IO на основе пути необходимого файла класса и вводит его в память через серию шагов анализа и инициализации. Загрузчики класса в Java включают в себя: Bootstrapclassloader (верхний слой), extclassloader, Appclassloader и пользовательский загрузчик (нижний слой). Для различных типов пакетов JAR (или файлов классов) JVM будет иметь различные типы загрузки классов для загрузки.
Соответствующие отношения следующие:
Bootstrapclassloader используется для загрузки классов, необходимых для работы JVM:
Java_home/jre/lib/resources.jar: java_home/jre/lib/rt.jar: java_home/jre/lib/sunrasign.jar: java_home/jre/lib/jsse.jar: java_home/jre/lib/jce.jar: java_home/jreset.jas/hares.jas.jas.jas.jas.jas.jas. Java_home/jre/lib/jfr.jar: java_home/jre/lib/classes
Extclassloader используется для загрузки классов расширения:
../Java/extensions: ../java_home/jre/lib/ext: ../library/java/extensions:/network/library/java/extensions: ../system/library/java/extensions: ../lib/java
Appclassloader используется для загрузки классов, созданных в разделе «Палаты класса», и классы, упомянутые в пакете JAR в нашем проекте.
Вся загрузка класса загружается с помощью механизма, называемого родительским делегацией.
Например, класс загружается погрузчиком с самым низким уровнем (пользовательский класс загрузчика). Этот загрузчик сначала вызовет загрузчик предыдущего уровня (Appclassloader) для загрузки, и загрузка Appclassloder будет продолжать передавать на верхний уровень (extclassloader) для загрузки до начальной загрузки. Если Classpath, загруженный Bootstrapclassloader, не может найти этот класс, он будет передан загрузчику (extclassloader) следующего слоя для загрузки. Если этот класс не может быть найден, он будет по -прежнему передавать следующему слою (AppClassLoader) для загрузки. И так далее, если пользовательский загрузчик не может найти этот класс, программа бросит ClassNotFoundError.
Весь процесс загрузки показан следующим образом:
(Изображение цитируется из: https://www.cnblogs.com/xing901022/p/4574961.html)
Отслеживание исходного кода источника загрузки класса заключается в следующем (исходный код был надлежащим образом упрощен здесь). Читатели могут нажать на исходный код для просмотра:
Пакет java.lang.classloader; импорт ...... Защищенный класс <?> LoadClass (String name, Boolean Resolve) Throws ClassNotFoundException {Synchronized (getClassLoadingLock (имя)) {// Сначала найдите в виртуальной машинной памяти, был ли этот класс загружен ... Основная проблема с Cache Lies! ! ! Класс <?> C = findloadclass (name); if (c == null) {long t0 = System.nanotime (); попробуйте {if (parent! = null) {// пусть предыдущий загрузчик слоя загружается первым c = parent.loadclass (name, false); } else {c = findbootStrapClassornull (name); }} catch (classnotfoundexception e) {// classnotfoundexception брошен, если класс не найден // из не нулевого загрузчика класса. }} if (Resolve) {ResolVeclass (c); } return c; }}Вы можете полностью оценить процесс механизма родительского делегирования в исходном коде, и были отмечены три наиболее важных предложения кода:
Если пользователю нужен пользовательский загрузчик и загрузите файл класса указанного пути, ему необходимо наследовать класс загрузку и реализовать метод FindClass (String name). В качестве примера:
пакет com.linuxidc.utils; import java.io.bytearrayoutputstream; import java.io.fileinputstream; import java.io.ioexception; import java.io.inputStream; Public Class ServiceClassLoader extends ClassLoader {Private String ClassPath; public serviceClassLoader (String classPath) {this.classpath = classPath; } /*** Перепишите метод FindClass родительского класса. CloadClass родительского класса будет называть этот метод */ @Override Protected Class <?> FindClass (String name) Throws ClassNotFoundException {class <?> C = null; byte [] classData = getClassData (имя); if (classdata! = null) {c = decipenclass (имя, classdata, 0, classdata.length); } else {бросить новый ClassNotFoundException (); } return c; } // Читать файл класса через поток iO и преобразовать его в массив Byte Private Byte [] getClassData (String name) {String path = classPath + "/" + name.replace ('.', '/') + ".Class"; InputStream iStream = null; BytearRayOutputStream BytearRayOutputStream = new BytearRayOutputStream (); try {iStream = new FileInputStream (path); Byte [] buffer = новый байт [1024]; int temp = 0; while ((temp = istream.read (buffer))! =-1) {bytearrayoutputstream.write (буфер, 0, темп); } if (bytearrayoutputstream! = null) {return bytearrayoutputstream.tobytearray (); }} catch (Exception e) {e.printstackTrace (); } наконец {try {if (iStream! = null) {istream.close (); }} catch (ioException e) {e.printstacktrace (); } try {if (bytearrayoutputstream! = null) {bytearrayoutputstream.close (); }} catch (ioException e) {e.printstacktrace (); }} return null; }}Код для использования загрузчика класса выглядит следующим образом:
ServiceClassLoader ServiceClassLoader = новый ServiceClassLoader ("c:/myClass"); czlass <?> C = serviceClassloader.loadClass ("com.linuxidc.service.myclass");Если вы используете один и тот же объект ServiceClassLoader для загрузки одного и того же файла класса несколько раз, объект класса после каждой нагрузки одинаковы! Однако, если новый различный пользовательский загрузчик загружает один и тот же файл класса, каждый раз возвращается другой объект класса.
ПРИМЕЧАНИЕ. Файл класса, который вы хотите загрузить, не может быть размещен в каталоге ClassPath и любых подкаталогах, в противном случае он будет загружен сначала AppClassLoader (это потому, что загрузка класса принимает родительский механизм делегирования, а загрузчик APPCLASSLER может загружать все файлы класса под класс). Каждый раз, один и тот же загрузка приложений загружается, поэтому будут проблемы с кэшированием класса.
Это решает проблему непосредственного использования отражения, когда загружается класс JVM.
Суммировать
Вышеуказанное - все содержание этой статьи. Я надеюсь, что содержание этой статьи имеет определенную справочную ценность для каждого обучения или работы. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения. Спасибо за поддержку Wulin.com.