Каждый класс будет использовать свой собственный загрузчик классов для загрузки других классов. Так что если ClassA.class
ссылки ClassB.class
тогда ClassB
должны быть на пути к классам загрузчика классовClassA
или его родителей.
Загрузчик классов контекста потока является текущим загрузчиком классов для текущего потока. Объект может быть создан из класса ClassLoaderC
и затем передан в поток, принадлежащий ClassLoaderD
. В этом случае объект необходимо использовать Thread.currentThread().getContextClassLoader()
напрямую, если он хочет загрузить ресурсы, которые недоступны в его собственном загрузчике классов.
ClassB
должен быть на classpathClassA
загрузчика (илиClassA
родителей загрузчика)? Не может лиClassA
загрузчик переопределитьloadClass()
, чтобы он мог успешно загружаться,ClassB
даже еслиClassB
он не находится в своем пути к классам?ClassA.class
ссылкиClassB.class
»?Это не отвечает на первоначальный вопрос, но поскольку вопрос высоко ранжируется и связывается для любого
ContextClassLoader
запроса, я думаю, что важно ответить на связанный вопрос о том, когда следует использовать загрузчик класса контекста. Краткий ответ: никогда не используйте загрузчик классов контекста ! Но установите его,getClass().getClassLoader()
когда вам нужно вызвать метод, который отсутствуетClassLoader
параметр.Когда код из одного класса просит загрузить другой класс, правильный загрузчик класса, который нужно использовать, является тем же загрузчиком класса, что и класс вызывающей стороны (т. Е.
getClass().getClassLoader()
). Именно так все и работает в 99,9% случаев, потому что именно это делает сама JVM. при первом создании экземпляра нового класса, вызове статического метода или обращении к статическому полю.Когда вы хотите создать класс с использованием отражения (например, при десериализации или загрузке настраиваемого именованного класса), библиотека, которая выполняет отражение, должна всегда спрашивать приложение, какой загрузчик классов использовать, получая в
ClassLoader
качестве параметра из приложения. Приложение (которое знает все классы, которые нужно построить) должно передать егоgetClass().getClassLoader()
.Любой другой способ получить загрузчик классов неверен. Если библиотека использует такие хаки, как
Thread.getContextClassLoader()
,sun.misc.VM.latestUserDefinedLoader()
илиsun.reflect.Reflection.getCallerClass()
это ошибка, вызванная недостатком API. По сути,Thread.getContextClassLoader()
существует только потому, что тот, кто разработалObjectInputStream
API, забыл принятьClassLoader
в качестве параметра, и эта ошибка преследует сообщество Java и по сей день.Тем не менее, многие классы JDK используют один из нескольких хаков, чтобы угадать какой-либо загрузчик классов. Некоторые используют
ContextClassLoader
(что дает сбой, когда вы запускаете разные приложения в общем пуле потоков, или когда вы покидаетеContextClassLoader null
), некоторые обходят стек (что не удается, когда прямой вызывающий класс сам является библиотекой), другие используют загрузчик системного класса (что нормально, если задокументировано использование только классов вCLASSPATH
) или загрузчике классов, а некоторые используют непредсказуемую комбинацию вышеперечисленных методов (что только делает вещи более запутанными). Это привело к сильному рыданию и скрежету зубов.При использовании такого API, сначала попробуйте найти перегрузку метода, который принимает загрузчик классов в качестве параметра . Если разумного метода нет, попробуйте установить
ContextClassLoader
вызов API before (и затем сбросить его):источник
На javaworld.com есть статья, которая объясняет разницу => Какой ClassLoader вы должны использовать
(1)
(2) из того же источника:
источник
bootstrap
загрузчика класса контекста устанавливается не родительский загрузчик классов, а загрузчик дочернегоsystem
класса classpath, с которымThread
он устанавливается. ЗатемJNDI
классы обязательно используютThread.currentThread().getContextClassLoader()
для загрузки классы реализации JNDI, доступные в пути к классам.Если добавить ответ @David Roussel, классы могут загружаться несколькими загрузчиками классов.
Давайте разберемся, как работает загрузчик классов .
Из блога Джавина Пола в javarevisited:
ClassLoader
следует трем принципам.Принцип делегирования
Bootstrap ClassLoader отвечает за загрузку стандартных файлов классов JDK из rt.jar и является родителем всех загрузчиков классов в Java. Загрузчик класса Bootstrap не имеет родителей.
Расширение ClassLoader делегирует запрос на загрузку класса своему родителю, Bootstrap и, в случае неудачи , загружает каталог формы jre / lib / ext или любой другой каталог, указанный системным свойством java.ext.dirs.
Загрузчик классов системы или приложения и отвечает за загрузку определенных классов приложения из переменной среды CLASSPATH, параметра командной строки -classpath или -cp, атрибута Class-Path файла Manifest внутри JAR.
Загрузчик классов приложений является дочерним по отношению к Extension ClassLoader и реализуется
sun.misc.Launcher$AppClassLoader
классом.ПРИМЕЧАНИЕ. За исключением загрузчика классов Bootstrap , который реализован на родном языке в основном на C, все загрузчики классов Java реализованы с использованием
java.lang.ClassLoader
.Принцип видимости
Принцип уникальности
источник