Модель делегирования Java ClassLoader? - PullRequest
12 голосов
/ 15 апреля 2010

При вызове loadClass() для ClassLoader, ClassLoader сначала проверяет, был ли загружен класс, или он немедленно делегирует эту проверку своему родителю ClassLoader?

Java API говорит:

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

Но в книге есть специальная глава о загрузчике классов Отражение Java в действии , в которой говорится:

Загрузчик классов вызывает findLoadedClass, чтобы проверить, был ли класс уже загружен. Если загрузчик классов не находит загруженный класс, вызывает loadClass для родительского загрузчика классов.

Что правильно?

Ответы [ 6 ]

17 голосов
/ 15 апреля 2010

Правильная реализация загрузчика классов будет:

  1. Проверьте, загружен ли уже класс.
  2. Обычно запрашивают загрузчик родительского класса для загрузки класса
  3. Попытка найти класс в его собственном пути к классу.

Реализация ClassLoader.loadClass по умолчанию выглядит примерно так:

protected synchronized Class<?> loadClass(String name, boolean resolve) {
  // First, check if this class loader has directly defined the class or if the
  // JVM has initiated the class load with this class loader.
  Class<?> result = findLoadedClass(name);
  if (result == null) {
    try {
      // Next, delegate to the parent.
      result = getParent().loadClass(name);
    } catch (ClassNotFoundException ex) {
      // Finally, search locally if the parent could not find the class.
      result = findClass(ex);
    }
  }
  // As a remnant of J2SE 1.0.2, link the class if a subclass of the class
  // loader class requested it (the JVM never calls the method,
  // loadClass(String) passes false, and the protected access modifier prevents
  // callers from passing true).
  if (resolve) {
    resolveClass(result);
  }
  return result;
}

Некоторые реализации загрузчика классов будут делегировать другим не родительским загрузчикам классов (например, OSGi делегирует граф загрузчиков классов в зависимости от пакета), а некоторые реализации загрузчиков классов будут искать классы в локальном пути к классам перед делегированием .

2 голосов
/ 15 апреля 2010

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

Когда запрашивается найти (внешние данные, которые описывают) класс или ресурс, экземпляр ClassLoader будет делегировать поиск (внешние данные, которые описывают) класс или ресурс для своего родительского загрузчика класса прежде чем пытаться найти (внешние данные, которые описывают) класс или сам ресурс.

Что не препятствует короткому замыканию, если он знает, что его родитель не может найти класс, но может (как показано ранее загружающим класс)

2 голосов
/ 15 апреля 2010

API Java правильный.

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

Из Механизма загрузки классов Java -

При загрузке класса загрузчик класса сначала «делегирует» поиск класса его загрузчику родительского класса, прежде чем пытаться найти сам класс.

1 голос
/ 15 апреля 2010

Это в основном, как это работает. Вы набираете

Foo f = new Foo();

В этот момент загрузчик классов определит, был ли загружен Foo() по его битам в memory / perm gen. Если он был загружен, используйте его. В противном случае делегируйте его загрузчику родительского класса, чтобы попытаться разрешить класс. Биты этого класса читаются с диска и затем загружаются в память. На следующем new Foo() класс теперь будет найден в памяти / загружен.

0 голосов
/ 07 июля 2010

В этом контексте следует отметить еще одну проблему. Документ API говорит:

Методы и конструкторы объекты, созданные загрузчиком классов, могут ссылки на другие классы. Определить упомянутый класс (ы), Java виртуальная машина вызывает loadClass метод загрузчика классов, который Первоначально создан класс.

Это означает, что сети ссылочных классов загружаются одним и тем же загрузчиком классов.

0 голосов
/ 15 апреля 2010

Чтобы согласиться с ответом Шри, он всегда будет делегирован родителю, и API верный. Если вы играете с загрузкой классов, это может немного усложнить задачу или добиться желаемого эффекта. Я бы предложил запустить jvm с минимальным путем к классам, а затем загрузить все классы с помощью вашего пользовательского загрузчика классов. Самый простой способ сделать это - использовать URLClassloader или составной объект, оборачивающий URLClassloader, чтобы вы могли отслеживать, какие классы загружаются и когда.

Также стоит помнить, что класс A, загружаемый загрузчиком классов C! = Класс A, загружаемый загрузчиком классов C, если C и D не являются частью одной и той же иерархии classloader-parent-child.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...