Как полезен следующий код Java в области автономных вычислений?

В книге, которую я изучаю, они показывают этот код Java:

Class c = ClassLoader.getSystemClassLoader().loadClass(name);
Class type = this.getClass().getClassLoader().loadClass(name);
Object obj = type.newInstance();

Этот код используется для динамической загрузки класса Java. Книга продолжается:

выгружает модули. Погрузчик классов не может выгрузить класс. Для разгрузки класса требуется разгрузка самого загрузчика класса. Вот почему программисты... имеют тенденцию определять несколько загрузчиков классов.

В чем преимущество использования такого кода? Идея автономных вычислений обычно - "вегетативное управление системой". Как это связано с тем, как Java-программа находится под управлением JVM?

источник: pg 166 проекта принципов автономных вычислений (по Лаланде)

Ответ 1

Преимущество заключается в том, что во время выполнения вы можете решить, какой класс фактически загружен и используется. Для простых программ Java, где у вас есть одна реализация класса, нет никакой выгоды.

Сложные среды, такие как Osgi (основа Eclipse), используют отдельные загрузчики классов для каждого модуля. Это обеспечивает гибкость и возможность замены модулей во время выполнения.

Другая "классическая" утилита - это загрузка драйвера базы данных во время выполнения. Возможно, вы захотите подключиться к базе данных MySQL или Oracle и использовать разные реализации JDBCDriver.

Дополнение:

Очень хорошая статья Alex Blewitt, в которой обсуждается концепция загрузки класса eclipse/osgi, можно найти здесь.

В моем собственном опыте кодирования я использовал плагины eclipse для проекта веб-мониторинга уровня предприятия. Мониторинг в основном связан с постоянным сбором некоторых ресурсов в сети. Каждый такой ресурс контролируется реализацией плагина монитора. Не все ресурсы контролируются нами, поэтому, когда они меняются, мы должны адаптировать плагин, который имеет дело с этим ресурсом. Все приложение мониторинга может продолжать работать, пока мы выгружаем старый модуль плагина против нового. Все во время выполнения, практически без простоя (только для модуля, который нужно было обменять). Конечно, мое использование загрузчика классов каждого плагина было неявным, используя платформу Eclipse Rich Client Platform (RCP). Вам просто нужно указать, какой плагин зависит от того, какая из них и фактическая загрузка класса затем выполняется платформой RCP.

Веб-серверы, такие как Tomcat, используют один и тот же подход, хотя у меня нет большого опыта работы с Tomcat.

Возможно, это хорошее упражнение для непосредственного внедрения динамической системы загрузки классов, но для приложений реального мира я бы окончательно рассмотрел реализации производственного уровня, например Eclipse RCP или Apache Karaf

Если вы хотите сделать все это на один шаг дальше и вам нужно запустить свои плагины в кластере, вы можете посмотреть Gyrex

Я не могу поделиться своим кодом здесь, но вот несколько отличных отправных точек с примерами кода:

Ответ 2

Предположим следующий пример. Вы разрабатываете программу. Пользователь может написать для него плагины (или агенты в контексте автономных программ). Ваша программа загрузит все плагины (или настраиваемые классы агентов), определенные в переменной конфигурации, например:

plugins: foo.bar.myplug,another.plugin

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

Кроме того, если по какой-либо причине вы хотите выгрузить эти классы (например, после перезаписи конфигурации), вам понадобится пользовательский загрузчик классов.

Добавление

Мы могли бы, например, представить себе программу с "миром", где взаимодействуют некоторые "агенты". В дополнение к нескольким агентам, включенным в основную программу, пользователь может создавать свои собственные агенты.

Основная программа позаботится о взаимодействии между агентами (мировые правила): отправляет события агентам; обновление состояния мира с учетом действий агентов; сохранять, загружать миры;....

Каждый агент - это один класс Java, который должен содержать метод "public Action handleEvent (Event)", который вызывается основной программой. По умолчанию существуют некоторые предопределенные классы, такие как "Person.class", "SearchRobot.class", каждый из которых имеет собственную реализацию "handleEvent". Все они дополняют абстрактный класс "Агент".

Программа позволяет пользователю создавать свои собственные агенты. Пользователь должен создать новый класс (продлить агент), содержащий метод "handleEvent". Возьмем, например, пользовательский класс "WalkerAgent.class", который имеет эвристический короткий путь для прохождения по всему миру.

Основная программа также будет иметь свойство "плагины". Это свойство должно содержать список агентов пользователя:

plugins: foo.bar.WalkerAgent 

когда запускается основная программа, она должна загружать все классы, перечисленные в свойстве "plugins". Что-то вроде (псевдокод):

 read property "plugins" and split it by ","
 for each split in previous:
    call loadClass

Чтобы создать новый экземпляр агента класса "WalkerAgent", вы не можете записать в основной программе "новый WalkerAgent()", потому что класс не существует, когда написана основная программа. Вместо этого вы должны вызвать "newInstance()" класса, который возвращает loadClass.

Теперь агент "WalkerAgent" готов к использованию так же, как предопределенные агенты "Person" и "RobotSearch".

(PS: очевидно, что в автономных вычислениях мир представляет собой, например, описание сети, а агенты выполняют такие действия, как "мониторинг IP", "оптимизатор маршрута",.... Этот пример использовал более простые концепции для упрощения понимание).