Есть несколько вещей, чтобы знать:
- Для большинства вещей, занимающейся контекстом загрузчика класса Нити является устаревшим, так как она не имеет никакого влияния. Это больше похоже на конвенцию; установка его оказывает влияние, если есть некоторые другие запросы кода и их использование. Для процесса загрузки стандартного класса он не имеет никакого значения. К сожалению, документация не упоминает об этом и делает его похожим на релевантную вещь. Возможно, он был предназначен иметь больше смысла, когда он был добавлен.
- В качестве pointed out by Erwin Bolwidt при загрузке
A
через ваш пользовательский загрузчик он делегирует его родительскому загрузчику, возвращая класс A
, загруженный родителем.
- Когда разрешает ссылки на класс, JVM всегда будет использовать , определяющий загрузчик реферера. Поэтому, когда ссылка из
A
на B
решена, виртуальная машина будет всегда использовать родительский загрузчик, который определен класс A
Последний пункт означает, что даже если вы измените свой пользовательский загрузчик классов, чтобы искать свои собственные классы первой вместо того, чтобы сначала следовать стандартной модели запроса родителя, она не решает проблему, если у нее нет собственного A
, так как тогда она все равно возвращает родительский A
, ссылки на которые будут разрешены с использованием родителя. Так как вы призываете defineClass
, прежде чем просить A
, порядок поиска не имеет значения, так как пользовательский загрузчик имеет уже определенный B
, что он возвращается, если кто-нибудь спросил его B
...
Так что вы можете позволить своему обычаю погрузчик также загружает и определяет A
. Или вы используете Reflection с переопределением доступа к defineClass
в системе ClassLoader
перед этим загружает B
. Самое чистое решение - реализовать логику модификации класса в качестве Java-агента, который может использовать API-интерфейс Instrumentation для перехвата и изменения определения B
сразу после его загрузки.
Класс «A» не загружен, так что дочерний элемент ClassLoader делегирует загрузку класса родительскому классу ClassLoader. Но B загружается в дочерний элемент (модифицированная версия загружается в дочерний элемент), поэтому, когда A требует B, потому что A расширяет B, почему B загружается из родителя (который загружает оригинал)? –
Что значит «Но B загружается в ребенка»? Если B существует в загрузчике родительского класса, то он не загружается в дочерний элемент, потому что каждый загрузчик классов, который не переопределяет первых делегатов loadClass, его родительскому элементу и будет пытаться загрузить его только в дочернем классе classlaoder, если он не найден в родительский –
Мне нужно изменить байт-код класса B во время выполнения. Итак, чтобы сохранить измененный класс B, я должен использовать child.defineClass(), потому что parent.defineClass() не отображается, а исходный класс B может существовать в родительском загрузчике классов. - B изменяются и загружается ребенок - А загружается из ребенка -> делегат родителей - А продолжается B - B, кажется, быть загружено из родительского - B не сохраняется на родитель, поэтому родитель нагрузка B с использованием URL-адреса Я думаю, - родительская нагрузка оригинала класса B - B загружается дважды: оригинал в родительском и изменен в дочернем. –