как обмениваться объектами между разными загрузчиками классов?

#java #classloader

#java #загрузчик классов

Вопрос:

Мне нужны разные загрузчики классов, чтобы иметь возможность выгружать классы. Но мне нужно обмениваться объектами между ними (на самом деле я получаю ClassCastException). Итак, каковы решения для решения этой проблемы?. Спасибо

Ответ №1:

Объекты из разных загрузчиков классов могут взаимодействовать друг с другом через интерфейсы и классы, загружаемые общим загрузчиком классов.

Комментарии:

1. я получаю ваш ответ. Но могу ли я получить экземпляр из внешнего объекта и сохранить его для непосредственного использования? Или мне нужно постоянно использовать интерфейсы для работы с другими объектами?

2. Энди попал в точку. Общий (родительский) загрузчик классов определяет интерфейс. Различные загрузчики классов загружают реализации интерфейса (или общего родительского элемента). Возьмите свой пирог и съешьте его тоже.

3. @Wyvern666, вы можете напрямую использовать экземпляр, класс которого определен через другой загрузчик классов, но только через типы времени компиляции, определенные через родительский загрузчик классов.

4. Двум плагинам, совместно использующим объекты, нужны ссылки на объекты, а объекты должны реализовывать тип, загружаемый родительским загрузчиком классов. Это можно сделать с помощью того же интерфейса, который используется родительским, или другого интерфейса. Ключевым моментом здесь является то, что загрузчики подключаемых классов делегируют их родителям перед загрузкой собственной копии класса. Итак, если вы включите тип интерфейса в classpath родительского загрузчика классов, то оба загрузчика подключаемых классов должны получить один и тот же класс через родительский загрузчик классов.

5. Единственный пример, который касается этого, который я нашел в быстром поиске в Google, относится к 1996 году, на полпути вниз по странице 4: javaworld.com/javaworld/jw-10-1996/jw-10-indepth.html?page=4 .

Ответ №2:

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

  1. Использование общего загрузчика классов

  2. Совместное использование библиотек в кластере

  3. Упаковка клиентского JAR для одного приложения в другое приложение

Обратитесь к этой ссылке для получения более подробной информации.

Комментарии:

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

2. Зависит от того, можно ли доверять плагинам или нет.

3. Да, на самом деле, плагины имеют доступ к основным классам приложений, но чего я не могу сделать, так это то, что плагины «видят друг друга».

4. Я знаю, что для Oracle Application Server между приложениями существует родительско-дочерняя связь, поэтому несколько дочерних приложений могут наследовать библиотеки от одного и того же родителя. Weblogic использует шаблоны для расширения домена. Попробуйте изучить что-то подобное в вашем контейнере.

Ответ №3:

Также будет упомянуто, что если вы используете интерфейсы, вы можете использовать java.lang.reflect.Proxy для создания экземпляра интерфейса, локального для вашего загрузчика классов, который под капотом выполняет вызовы с отражением «реального» (внешнего) объекта из другого загрузчика классов. Это некрасиво, и если параметры или возвращаемые типы не являются примитивными, вы просто передадите ClassCastException дальше по строке. Хотя вы можете что-то придумать, чтобы это работало, в общем, лучше либо иметь родительский загрузчик классов с некоторыми общими типами, которые вы хотите иметь возможность использовать во всех загрузчиках классов, либо использовать более … сериализованный формат для связи (медленнее), либо использовать только общие интерфейсы, которые работают с примитивами.

Ответ №4:

В какой-то ситуации может быть приемлемо «переключить контекст» с помощью использования потока с нужным загрузчиком классов. Например, вы создаете SingleThreadPoolExecutor в нужном вам контексте и используете этот одноэлементный экземпляр для выполнения кода из другого контекста.

Вот моя ситуация: многомодульное веб-приложение maven развернуто в tomcat. В одном веб-приложении зарегистрирован компонент службы уведомлений об ошибках, и DefaultUncaughtExceptionHandler для всей JVM используется компонент для отправки сообщения об ошибке по электронной почте (с дополнительной логикой внутри). Когда исключение было сгенерировано веб-приложением, которое создало электронное письмо bean, было успешно отправлено, когда исключение было сгенерировано другим веб-приложением, функциональность электронной почты не справлялась с классами javax.mail (что удивительно, но не само исключение). Когда я выполнил метод, который отправляет электронную почту в исполнителе, оба случая начинают работать.