Как динамически загружать класс из приложения JAR для использования в другом JAR?

У меня есть JAR-приложение, M.jar, которое поддерживает динамические записи и загрузку расширений. Приложение требует, чтобы классы реализовывали интерфейс E и назывались NE.

Теперь я пытаюсь сделать следующее:

  1. Напишите расширение API1 и загрузите его в M.
  2. Напишите другое расширение APIUser, загрузите его в M и используйте API1.

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

введите здесь описание изображения

Я знаю, что M.jar использует собственный ClassLoader, потому что он требует, чтобы любое расширение называлось только AE.

Я попробовал метод ServiceProvider, ServiceProviderInterface, как описано здесь, но это не сработало. Я считаю, что это связано с тем, что классы API не находятся в пути к классам M, и поэтому APIUser не может его найти.

Я хочу знать,

  1. Если возможно использовать ClassLoader APIUser для загрузки класса API и его инициализации для использования в APIUser.
  2. Может ли M заблокировать/изолировать ClassLoader API от любых других расширений? Я думаю, что это может быть основано на этом ответе.
  3. Какие еще есть средства для загрузки класса API в APIUser1 или APIUSer2... и поддержки только одного экземпляра класса API? (т.е. синглтон)

person htcm8    schedule 11.06.2018    source источник
comment
java.net.URLClassLoader.   -  person user207421    schedule 12.06.2018
comment
Вы знаете OSGi? Я думаю, что ваша мысль похожа на системную архитектуру OSGi.   -  person hiropon    schedule 12.06.2018
comment
А почему ServiceLoader у вас не сработало? Вы можете применить все эти проверки.   -  person user207421    schedule 12.06.2018
comment
@EJP Я не знаю, почему у меня не работает ServiceLoader. Я предполагаю, что, вероятно, потому, что классы API не находятся в пути к классам, как M? Или, по крайней мере, APIUser не может найти эти классы/услуги. Мой итератор из APIUser всегда возвращает пустые экземпляры. И я не хочу использовать URLClassLoader, потому что я не хочу, чтобы APIUser выполнял пользовательскую загрузку. Если это поможет, разработчики M.jar подтвердили, что они используют отдельные загрузчики классов для каждого из своих расширений.   -  person htcm8    schedule 12.06.2018
comment
@hiropon Я посмотрю на это. Спасибо.   -  person htcm8    schedule 12.06.2018


Ответы (1)


После некоторого исследования и изучения ClassLoaders, вот что я узнал по своим вопросам.

  1. Это невозможно сделать, потому что таким образом M.jar и другие расширяемые Java-программы загружают другой, используя URLClassLoader как дочерний элемент какого-либо другого ClassLoader. Это означает, что в иерархии делегирования ClassLoader ClassLoader API.jar находится выше в иерархии, а ClassLoader APIUser.jar будет родственным. Это означает, что классы, загруженные из API.jar, не видны в APIUser.jar.

  2. M не изолирует расширения явно, но это естественный способ загрузки файлов JAR в приложение.

  3. Основываясь на ответе на вопрос 1, я сейчас делаю это с помощью хакерский способ добавить JAR в путь к классам SystemClassLoader во время выполнения, а затем ссылаться на него из других/любых расширений, загружая его с помощью SystemClassLoader. Это связано с тем, что SystemClassLoader виден из любых расширений.

ПРИМЕЧАНИЯ. Я также предполагаю, что способ ServiceLoader также будет работать. Но я сам не пробовал.

Использованная литература:

https://zeroturnaround.com/rebellabs/rebel-labs-tutorial-do-you-really-get-classloaders/

https://docs.oracle.com/javase/8/docs/api/java/lang/ClassLoader.html

person htcm8    schedule 18.06.2018