интервьюер:Почему бы вам сегодня подробно не рассказать о механизме родительского делегирования?
Кандидат:хорошо.
Кандидат: Как упоминалось в прошлый раз: файлы классов загружаются в JVM через "загрузчик классов"
Кандидат: Чтобы предотвратить существование в памяти нескольких копий одного и того же байт-кода, используется механизм родительского делегирования (он не будет пытаться загрузить класс сам по себе, а делегирует запрос родительскому загрузчику для завершения, а затем идет вверх )
Кандидат: Классы собственных методов в JDK обычно загружаются корневым загрузчиком (загрузчиком Bootstrp), классы расширений, реализованные в JDK, обычно загружаются загрузчиком расширений (ExtClassLoader), а файлы классов в программе загружаются системой. загрузчик (AppClassLoader) Реализовать загрузку.
Кандидат: Это должно быть легко понять, верно?
интервьюер: Воробей ест (действительно)!
интервьюер:В продолжение темы хотелось бы спросить, что значит сломать механизм родительского делегирования?
Кандидат: Легко понять, это означает: пока я загружаю класс, я не ищу его в порядке APPClassLoader->Ext ClassLoader->BootStrap ClassLoader, тогда он сломан.
Кандидат: поскольку метод загрузки ядра класса находится в методе loadClass класса LoaderClass (основная реализация механизма родительского делегирования).
Кандидат: Затем, пока я настрою ClassLoader и перепишу метод loadClass (не начинайте искать загрузчик классов в соответствии с вышеизложенным), это будет считаться нарушением механизма родительского делегирования.
интервьюер:Так просто?
Кандидат: Ну, это так просто
интервьюер:Знаете ли вы сцену, в которой нарушается механизм родительского делегирования?
Кандидат: Самый очевидный из них — Tomcat.
интервьюер: Расскажите подробнее?
Кандидат: При развертывании проекта в начале мы помещаем пакет war под веб-приложение tomcat, что означает, что один tomcat может запускать несколько веб-приложений (:
Кандидат:правильно?
интервьюер: Эм..
Кандидат: Предположим, теперь у меня есть два веб-приложения, каждое из которых имеет класс с именем User, и оба имеют одно и то же полное имя класса, например com.yyy.User. Но их конкретная реализация отличается
Кандидат: Так как же Tomcat гарантирует, что они не будут конфликтовать?
Кандидат: Ответ заключается в том, что Tomcat создает экземпляр загрузчика классов (WebAppClassLoader) для каждого веб-приложения. Загрузчик переписывает метод loadClass и сначала загружает классы в текущий каталог приложения.
Кандидат: тогда достигается изоляция уровня веб-приложений.
интервьюер:Знаете ли вы, что у Tomcat есть и другие загрузчики классов?
Кандидат: ну я знаю
Кандидат: Не все зависимости под веб-приложением нужно изолировать.Например, Redis можно разделить между веб-приложениями (при необходимости), потому что если версия одинаковая, нет необходимости загружать отдельную копию для каждого веб-приложения. .
Кандидат: Подход тоже очень простой.Tomcat добавляет загрузчик родительского класса (SharedClassLoader) в WebAppClassLoader.Если сам WebAppClassLoader не загружается в определенный класс, то делегируйте SharedClassLoader для его загрузки.
Кандидат: (Это не что иное, как размещение классов, которые должны быть разделены между приложениями, в общий каталог)
интервьюер: Эм..
Кандидат: Чтобы изолировать веб-приложение от классов самого Tomcat, существует загрузчик классов (CatalinaClassLoader) для загрузки зависимостей самого Tomcat.
Кандидат: если собственные зависимости и веб-приложения Tomcat также необходимо использовать совместно, то имеется также загрузчик классов (CommonClassLoader) для загрузки и последующего совместного использования.
Кандидат: Каталог загрузки каждого загрузчика классов можно просмотреть в файле конфигурации catalina.properties tomcat.
Кандидат: Позвольте мне немного нарисовать диаграмму структуры загрузки классов Tomcat, иначе она будет немного абстрактной.
интервьюер: Ну да ладно, понимаю, немного интересно.
интервьюер:Кстати, хочу спросить, вы не знаете JDBC, я слышал, что он также разрушает модель родительского делегирования, как вы это понимаете.
Кандидат: Эмм, это вопрос мнения, сломано это или нет.
Кандидат: JDBC определяет интерфейс, а определенные классы реализации реализуются различными производителями (например, MySQL).
Кандидат: Существует правило для загрузки классов: если класс загружается загрузчиком классов А, то зависимые классы этого класса также загружаются "тем же самым загрузчиком классов".
Кандидат: Когда мы используем JDBC, мы используем DriverManager для получения Connection.DriverManager загружается загрузчиком классов BootStrap в пакете java.sql.
Кандидат: Когда мы используем DriverManager.getConnection(), мы должны получить класс, реализованный производителем.
Кандидат: Но сможет ли BootStrap ClassLoader загружать классы, реализованные разными производителями?
Кандидат: Очевидно нет, этих классов реализации нет в пакете java, как их можно загрузить?
интервьюер: Эм..
Кандидат: Решение для DriverManager состоит в том, чтобы получить «загрузчик контекста потока» при инициализации DriverManager.
Кандидат: при получении соединения «Загрузчик контекста потока» используется для загрузки соединения, а загрузчик контекста потока здесь на самом деле является App ClassLoader.
Кандидат: Таким образом, когда вы получаете Connection, вам все равно нужно сначала найти Ext ClassLoader и BootStrap ClassLoader, но эти два загрузчика не могут быть загружены и в конечном итоге будут загружены App ClassLoader.
интервьюер: Эм..
Кандидат: В этом случае некоторые люди думают, что механизм родительского делегирования разрушен, потому что он должен быть загружен BootStrap ClassLoader, но вы пришли к "Thread Context Loader" и изменили "Class Loader"
Кандидат: Некоторые люди думают, что механизм родительского делегирования не уничтожается, а заменяется на "загрузчик контекста потока" для загрузки классов, но они все равно следуют: "Поищите загрузчик родительского класса для загрузки по очереди, и только тогда, когда вы можете" не найдешь, сделай сам. загрузи». Что "принцип" не изменился.
интервьюер: Тогда я понимаю
Резюме этой статьи:
-
Необходимые знания:В JDK есть три загрузчика классов по умолчанию: AppClassLoader, Ext ClassLoader и BootStrap ClassLoader. Родительским загрузчиком AppClassLoader является Ext ClassLoader, а родительским загрузчиком Ext ClassLoader — BootStrap ClassLoader. Родительско-потомковые отношения здесь достигаются не наследованием, а композицией.
-
Что такое механизм родительского делегирования:В процессе загрузки загрузчика класс сначала передается загрузчику родительского класса для загрузки, и загрузчик родительского класса не обнаруживается до тех пор, пока не будет загружен сам.
-
Назначение механизма родительского делегирования:Чтобы предотвратить несколько копий одного и того же байт-кода в памяти (безопасность)
-
Правила загрузки класса:Если класс загружается загрузчиком классов A, то зависимые классы этого класса также загружаются «одним и тем же загрузчиком классов».
-
Как сломать механизм родительского делегирования:Настроить ClassLoader и переписать метод loadClass (до тех пор, пока он не будет передан родительскому загрузчику для загрузки по очереди, даже если механизм родительского делегирования не работает)
-
Примеры нарушения механизма родительского делегирования: Tomcat
- Для изоляции классов веб-приложений создайте загрузчик классов WebAppClassLoader для каждого приложения.
- Для совместного использования классов веб-приложений используйте ShareClassLoader в качестве загрузчика родительского класса для WebAppClassLoader. Если загрузчик WebAppClassLoader не может быть найден, попробуйте загрузить его с помощью ShareClassLoader.
- Чтобы изолировать сам Tomcat от классов веб-приложений, используйте загрузчик классов CatalinaClassLoader для изоляции, а CatalinaClassLoader загружает собственные классы Tomcat.
- Чтобы Tomcat мог совместно использовать классы с веб-приложениями, используйте CommonClassLoader в качестве загрузчика родительских классов для CatalinaClassLoader и ShareClassLoader.
- Каталоги ShareClassLoader, CatalinaClassLoader и CommonClassLoader можно настроить в catalina.properties Tomcat.
-
Загрузчик контекста потока:Из-за правил загрузки классов очень вероятно, что родительский загрузчик зависит от классов дочернего загрузчика при загрузке, что приводит к невозможности успешной загрузки (BootStrap ClassLoader не может загружать классы сторонних библиотек), поэтому существует "загрузчик контекста потока" для загрузки.
Добро пожаловать в мой публичный аккаунт WeChat【Java3y] Давайте поговорим о Java-интервью, серия онлайн-интервьюеров постоянно обновляется!
Серия [Онлайн-интервьюер-Мобильный терминал]Продолжаем обновлять два раза в неделю!
【Онлайн-интервьюер-компьютер】СерияПродолжаем обновлять два раза в неделю!
Оригинал это не просто! ! Проси три! !