Проблема в том, что по какой-то причудливой причине мне приходится загружать интерфейс Inter с дочерним ClassLoader и класс реализации Impl с родительским ClassLoader.
Я не могу понять, почему дочерний загрузчик классов должен загружать интерфейс, оставляя родительский загрузчик классов для загрузки реализации. Это неизбежно вызовет проблемы, так как в механизме загрузки классов, используемом JVM, нет механизма, позволяющего отложить загрузку классов дочернему загрузчику классов. Обычный механизм реализации поведения загрузки классов в JVM определен в документации API класса ClassLoader:
Класс ClassLoader использует модель делегирования для поиска классов и ресурсов. Каждый экземпляр ClassLoader имеет связанный загрузчик родительского класса. При запросе на поиск класса или ресурса экземпляр ClassLoader делегирует поиск класса или ресурса своему загрузчику родительского класса, прежде чем пытаться найти сам класс или ресурс. Встроенный загрузчик классов виртуальной машины, называемый «загрузчиком классов начальной загрузки», сам по себе не имеет родителя, но может служить родителем экземпляра ClassLoader.
Можно написать собственный загрузчик классов, расширив класс ClassLoader. и переопределить метод loadClass(). Расширение этого метода позволяет вам изменить делегирование загрузки класса одним из двух способов:
- Сначала родитель: заставить родительский загрузчик классов сначала загрузить класс. Обычно это транзитивное поведение — большинство родительских загрузчиков классов откладывают загрузку до своего родителя и т. д., пока в иерархии загрузчиков классов не будет достигнут загрузчик классов начальной загрузки (корневой). Если родительскому загрузчику классов не удается загрузить класс, дочерний пытается загрузить его. Возможный сбой при загрузке класса должен привести к созданию исключения ClassNotFoundException.
- Родитель-последний: пользовательский загрузчик классов пытается сначала загрузить класс, прежде чем делегировать его родительскому элементу. Родительские загрузчики классов используются только тогда, когда попытка дочернего элемента загрузить класс не удалась.
Большинство загрузчиков классов реализованы как загрузчики классов, ориентированные на родителей. Это связано с тем, что механизм делегирования может перемещаться по дереву вверх, но не вниз.
Если вы действительно хотите делегировать загрузку и поиск классов дочерним загрузчикам классов в иерархии, вам придется управлять ссылками на них в пользовательском загрузчике классов для родителя. Это непросто и обычно не делается вообще, за исключением очень исключительных обстоятельств, поскольку очень легко получить ужасные ClassNotFoundException и NoClassDefFoundError, поскольку нужно быть осторожным, чтобы загружать только необходимые классы из дочерних загрузчиков классов, в то время как остальные должны всегда откладываться на родителя (если я не ошибаюсь, функция общих библиотек в определенных контейнерах Java EE реализована таким образом).
Сказав это, идеальным решением было бы попытаться загрузить как интерфейс, так и классы реализации в родительском загрузчике классов и полагаться на механизм делегирования, чтобы гарантировать, что классы видны обоим загрузчикам классов; родитель может «видеть» классы, загруженные им самим, а потомок может «видеть» родительские классы.
PS: не забудьте использовать AccessController.doPrivileged при загрузке и определении классов. .
person
Vineet Reynolds
schedule
18.08.2010