этап загрузки класса
Этап загрузки класса делится на три этапа: загрузка, подключение и инициализация, и на этапе загрузки необходимо получить поток двоичных байтов, определяющий этот класс, через полное имя класса.Java намеренно извлекает этот шаг, чтобы реализовать его с помощью загрузчика классов.. Извлечение этого шага позволяет приложению настроить загрузчик классов по мере необходимости. А благодаря загрузчику классов в JAVA можно применять OSGI, горячее развертывание и другие поля.
на ЯвеЛюбой класс определяется самим классом и загрузчиком классов, который загружает класс для определения уникальности класса в JVM.. То есть вы загружаете его своим загрузчиком класса Аcom.aa.ClassA
и ваш загрузчик класса A загруженcom.aa.ClassA
Они разные, т.instanceof
Все сравнения разные. Таким образом, хотя они оба из одного и того же файла класса, но загружены разными загрузчиками классов, которые представляют собой два отдельных класса.
Помимо использования для загрузки классов, загрузчики классов также могут использоваться в качестве иерархии классов. Сама Java предоставляет 3 загрузчика классов
1. Bootstrap ClassLoader, который является частью самой виртуальной машины, реализован на C++ и в основном отвечает за загрузку<JAVA_HOME>\lib
Файл в каталоге или по пути, указанному параметром -Xbootclasspath, и имя которого распознается виртуальной машиной. Это отец всех загрузчиков классов.
2. Расширение ClassLoader (Расширение ClassLoader), которое реализовано на Java, не зависит от виртуальной машины, и в основном отвечает за загрузку<JAVA_HOME>\lib\ext
Библиотеки классов в каталоге или по пути, указанному в системной переменной java.ext.dirs.
3. Application ClassLoader (Приложение ClassLoader), которое реализовано на Java и не зависит от виртуальной машины. Он в основном отвечает за загрузку библиотеки классов по пользовательскому пути к классам (classPath).Если мы не реализуем собственный загрузчик классов, эта штука будет загрузчиком по умолчанию в нашей программе.
Модель родительского делегирования
Зная приведенные выше концепции, вы можете взглянуть на модель родительского делегирования.
Родительское делегирование означает, что если загрузчику класса необходимо загрузить класс, он сначала делегирует запрос класса загрузчику родительского класса для его завершения, и это имеет место на каждом уровне. Он рекурсивно переходит на верхний уровень, и когда родительский загрузчик не может выполнить запрос, подкласс попытается загрузить его. Родители здесь фактически относятся к родительскому классу, а не к матери. Родительский класс — это не то отношение наследования, о котором мы обычно говорим, но логика вызова выглядит так.
{
// First, check if the class has already been loaded 先判断class是否已经被加载过了
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false); //找他爸爸去加载
} else {
c = findBootstrapClassOrNull(name); //没爸爸说明是顶层了就用Bootstrap ClassLoader去加载
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name); //最后如果没找到,那就自己找
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
Модель родительского делегирования не является обязательным ограничением, т. е. вы не получите ошибку, если не сделаете этого, разработчики JAVA рекомендуют использовать загрузчики классов.
Каковы преимущества родительского делегирования? Это делает класс иерархическим разделением. просто возьмиjava.lang.Object
Например, вы загружаете его через уровни делегатов и в конечном итогеBootstrap ClassLoader
для загрузки, то есть он в конечном итоге загружаетсяBootstrap ClassLoader
иди найди<JAVA_HOME>\lib
в rt.jarjava.lang.Object
загружается в JVM.
Таким образом, если некоторые преступники создают свои собственныеjava.lang.Object
,В нем заложен плохой код.Если мы реализуем его по модели родительского делегирования, то в итоге в JVM будут загружены только вещи из нашего rt.jar, то есть коды этих основных базовых классов защищены. Из-за этого механизма в системе появится только одинjava.lang.Object
. Бардака не будет. Подумайте об этом, если бы в нашей JVM было два объекта, это был бы беспорядок.
Так что, поскольку эта модель рекомендуется, это, безусловно, имеет смысл.
Но в девяти случаях из десяти все идет не по-твоему,В некоторых случаях это ограничение должно быть нарушено., например JDBC.
Сначала вы должны знать SPI (интерфейс поставщика услуг), который отличается от API, он ориентирован на расширение, то есть я определил этот SPI, и как его реализовать реализуется расширителем. Я просто установил правило.
JDBC такой, этот SPI определен в rt.jar, mysql имеет реализацию jdbc mysql, oracle имеет реализацию jdbc oracle, в любом случае, мне все равно, как вы реализуете это в java, в любом случае, вы все должны следовать за мной, так что Мы, Java-разработчики, можем легко вызывать операции с базой данных. Поэтому из-за этого вы должны нарушить это ограничение.Bootstrap ClassLoader
Подклассы должны быть делегированы для загрузки конкретных реализаций, предоставляемых поставщиками баз данных. Потому что его руки могут только касаться<JAVA_HOME>\lib
, в остальном он ничего не может сделать. Это нарушает восходящий механизм делегирования.
Java имеет загрузчик класса контекста потока, черезsetContextClassLoader()
По умолчанию используется загрузчик класса приложения, а затемThread.current.currentThread().getContextClassLoader()
Получите загрузчик классов для загрузки.
Если есть ошибки, поправьте меня!
Личный публичный аккаунт: стратегия прокачки да
Имеются соответствующие расширенные материалы интервью (распространение, настройка производительности, классическая книга в формате pdf), ожидающие сбора.