Загрузчик системных классов Java на самом деле не заменяется

Можно ли действительно заменить загрузчик классов Java System?

В Java есть свойство -Djava.system.class.loader для замены загрузчика системных классов.

Однако любой класс, созданный с использованием новый, а не .newInstance(), показывает AppClassLoader в качестве загрузчика классов.

AppClassLoader также известен как загрузчик системных классов, поэтому не похоже, что происходит какая-либо реальная замена.

Например, при запуске (Oracle Hotspot в Windows JDK 1.8)

// Run with java -Djava.system.class.loader=classLoaders.MyClassLoader Example

public class MyClassLoader extends ClassLoader {
    public MyClassLoader(ClassLoader parent) {
        super(parent);
    }

    @Override
    public Class loadClass(String name) throws ClassNotFoundException {
        System.out.println("Loading class :" + name);
        return super.loadClass(name);
    }
}

class A {
}

public class Example {
    public static void main(String[] args) throws Exception {
        System.out.println(ClassLoader.getSystemClassLoader());
        System.out.println(new Example().getClass().getClassLoader());
        System.out.println(new A().getClass().getClassLoader());
    }
}

Результат:

Loading class :classLoaders.Example
classLoaders.MyClassLoader@6d06d69c
sun.misc.Launcher$AppClassLoader@58644d46
sun.misc.Launcher$AppClassLoader@58644d46

Пока первый экземпляр Example загружается с помощью MyClassLoader, а метод getSystemClassLoader возвращает MyClassLoader, любой класс, созданный с помощью новый, загружается исходным загрузчиком системных классов, так что именно заменяется?

Отвечает ли это на ваш вопрос? Почему не работает пользовательский системный загрузчик классов?

Jason Law 08.09.2020 09:56
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
1 257
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вам следует переопределить метод toString () вашего MyClassLoader и посмотреть, работает ли он.

В самой ранней последовательности загрузки JVM должен быть загрузчик классов для загрузки класса, переопределяющего загрузчик классов. Для этого также должен быть загружен ряд других классов, чтобы реализовать первоначальный загрузчик классов и построить достаточно JVM, чтобы должным образом принять перезаписанный загрузчик классов.

После того, как загрузчик классов был успешно переопределен, он должен вызывать ваше переопределение для остальных классов.

Это означает, что вы должны позаботиться о том, чтобы ранние вызовы загрузчика классов нереализованной версии не воспринимались как ошибки.

Ответ принят как подходящий

Вы просто расширяете ClassLoader и используете super.loadClass(); Итак, какой-то другой настоящий загрузчик классов выполняет фактическую загрузку класса.

За кулисами кажется, что система передает свои полномочия загрузчику классов System после того, как вы перейдете к загрузке.

Здесь уже дан ответ на тот же вопрос: https://stackoverflow.com/a/25493910/1364747

  1. MyClassLoader - это начальный загрузчик классов
  2. AppClassLoader - это определяющий загрузчик классов
  3. Все классы, загруженные в один и тот же пакет, связаны с определением загрузчика классов (который фактически загрузил первый класс в пакете).

A class loader L may create C by defining it directly or by delegating to another class loader. If L creates C directly, we say that L defines C or, equivalently, that L is the defining loader of C.

When one class loader delegates to another class loader, the loader that initiates the loading is not necessarily the same loader that completes the loading and defines the class. If L creates C, either by defining it directly or by delegation, we say that L initiates loading of C or, equivalently, that L is an initiating loader of C.

At run time, a class or interface is determined not by its name alone, but by a pair: its binary name (§4.2.1) and its defining class loader. Each such class or interface belongs to a single run-time package. The run-time package of a class or interface is determined by the package name and defining class loader of the class or interface.

Хотя MyClassLoader вызывает super.loadClass, реализация ClassLoader-> loadClass только находит другой экземпляр и делегирует ему полномочия.

Таким образом, реализация родительского класса только передает задание другому экземпляру.

Нет, дело не в этом. Например, определение класса A {} и использование New никогда не достигает System.out.println внутри MyClassLoader, что до делегирования

Gonen I 20.11.2018 00:52

Класс загружается только один раз. Пример уже загружен. Итак, он больше не загружается. Это могло быть причиной. Возможно, вам придется попробовать другой общедоступный класс в том же пакете. Потом проверьте результат.

Teddy 20.11.2018 00:58

В конце концов, загрузка Example была делегирована AppClassLoader. Итак, все "новое" изнутри Example будет поступать только в AppClassLoader. Возможно :) Попробуйте загрузить один байт класса самостоятельно. И делегирую другому ..

Teddy 20.11.2018 01:02

Вероятно, поэтому вместо наследования используется делегирование. Так что loadClass любого родительского загрузчика может быть вызван извне.

Teddy 20.11.2018 01:10

Другие вопросы по теме