Подтвердить что ты не робот

Деление и иерархия наследования UrlClassLoader

Я был смущен иерархией делегирования UrlClassLoader и иерархией наследования. Я создал класс, который расширяет UrlClassLoader и выполняется: childOfUrlClassLoader.getParent().getClass().getName() который дал мне: sun.misc.Launcher$AppClassLoader. После этого я посещу упомянутый выше класс (источник)

249 static class AppClassLoader extends URLClassLoader {
        //...
308     protected synchronized Class<?> loadClass(String name, boolean resolve)
309         throws ClassNotFoundException
310     {
311         // First, check if the class has already been loaded
312         Class c = findLoadedClass(name);
313         if (c == null) {
314             try {
315                 if (parent != null) {
316                     c = parent.loadClass(name, false);
317      
          // ...
329         return c;
330     }

Затем я проверил, кто является родителем AppClassLoader. Ожидается, что я получил sun.misc.Launcher$ExtClassLoader, а родительский элемент ExtClassLoader - null.


У меня есть несколько вопросов:

1) Кто загружает мой класс, так как код AppClassLoader.loadClass имеет строку

294    return (super.loadClass(name, resolve));

Это похоже на цикл, не так ли?

2) Почему ExtClassLoader не имеет BootstrapClassLoader как родителя, но имеет null?

3) Для чего класс AppClassLoader расширяет UrlClassLoader?

4b9b3361

Ответ 1

Первая модель-делегат

Встроенные java ClassLoaders следуют за первой моделью делегата. Это означает, что ClassLoader позволит родительскому элементу загружать класс, прежде чем он попытается загрузить его самостоятельно. В иерархии загрузчиков находится загрузочный загрузчик вверху, за которым следует расширитель классов классов, загрузчик классов приложений. Под приложением classloader можно найти URLClassLoaders и любые другие загрузчики, созданные приложением.

Загрузочный загрузчик bootstrap может загружать файлы из rt.jar, который содержит наиболее важные классы java, в том числе в пакетах java.lang, java.io, java.util и java.net. Расширитель классов классов загружает классы из других файлов jar в java-установке. Это загрузчик классов приложений, который загружает классы, найденные в пути к классам, и который является текущим загрузчиком классов при запуске приложения.

Загрузка в действии

Итак, что происходит, когда приложение хочет загрузить HashMap? Текущему загрузчику классов предлагается загрузить класс HashMap. Прежде чем пытаться что-либо предпринять, он запрашивает у своего родителя загрузчика классов расширения. В свою очередь расширитель классов классов разбивается на загрузчик bootstrap, который находит класс в rt.jar и загружает его.

Если класс, который нужно загрузить, находится в пути к классам, запрос переходит к загрузчику классов bootstrap, как и прежде, чтобы проверить rt.jar. Загрузочный загрузчик не может найти класс, поэтому задача возвращается к расширительному классу-загрузчику, который ищет установку java для класса. Когда это не удается, задача возвращается к загрузчику классов приложений, который сканирует путь к классу для класса.

Кэш ClassLoader

На практике каждый загрузчик классов имеет кэш, в котором хранятся уже загруженные классы, и поиск кеша выполняется до делегирования родительскому элементу, но это не меняет принцип делегирования в первую очередь.

Здесь проверяется кеш

Class c = findLoadedClass(name);

URLClassLoaders

URLClassLoader, созданный приложением, будет иметь приложение ClassLoader в качестве родителя. Если он следует за первой моделью делегата, классы будут найдены в пути к классам перед указанным URL.

Вопросы

1) Кто загружает мой класс

Я вижу немного другой код в вашей ссылке

309         // First, check if the class has already been loaded
310         Class c = findLoadedClass(name);
311         if (c == null) {
312             try {
313                 if (parent != null) {
314                     c = parent.loadClass(name, false);
315                 } else {
316                     c = findBootstrapClass0(name);
317                 }
318             } catch (ClassNotFoundException e) {
319                 // If still not found, then invoke findClass in order
320                 // to find the class.
321                 c = findClass(name);
322             }
323         }

Если класс не загружается родителем, он выдает исключение ClassNotFoundException, которое поймано, и позволяет текущему ClassLoader находить класс

321                 c = findClass(name);

2) Почему ExtClassLoader не имеет BootstrapClassLoader в качестве родителя, но имеет значение null?

На это отвечает API getClassLoader

[getClassLoader()] возвращает загрузчик класса для класса. В некоторых реализациях может использоваться значение null для представления загрузчика класса загрузки.

3) Для чего класс AppClassLoader расширяет UrlClassLoader?

Учтите, что загрузчик классов приложений не является особенным в том, что он загружает классы, предоставленные пользователем, а не системные классы. Путь к классам фактически является списком URI, поэтому URLClassLoader является подходящим суперклассом.

Ссылки

Есть много статей по загрузке классов, включая