Java, Classpath, Classloading => Несколько версий одного и того же JAR / проекта
79490 просмотра
5 ответа
Я знаю, что это может быть глупый вопрос для опытных программистов. Но у меня есть библиотека (клиент http), которая требуется для некоторых других фреймворков / jar-файлов, используемых в моем проекте. Но все они требуют разных основных версий, таких как:
httpclient-v1.jar => Required by cralwer.jar
httpclient-v2.jar => Required by restapi.jar
httpclient-v3.jar => required by foobar.jar
Является ли загрузчик классов достаточно умным, чтобы как-то их разделить? Скорее всего нет? Как Classloader справляется с этим, если класс одинаков во всех трех банках. Какой из них загружен и почему?
Classloader подхватывает только один jar или он смешивает классы произвольно? Так, например, если класс загружен из Version-1.jar, все другие классы, загруженные из того же загрузчика классов, все попадут в тот же самый jar?
Как вы справляетесь с этой проблемой?
Есть ли какая-то хитрость, чтобы каким-то образом «включить» банки в «required.jar», чтобы они рассматривались как «одна единица / пакет» Classloader
или как-то связаны?
Ответы (5)
54 плюса
Проблемы, связанные с загрузкой классов, довольно сложны. В любом случае вы должны иметь в виду некоторые факты:
Загрузчики классов в приложении обычно больше, чем один. Загрузчик класса загрузчика делегирует соответствующий. Когда вы создаете новый класс, вызывается более специфический загрузчик классов. Если он не находит ссылку на класс, который вы пытаетесь загрузить, он делегирует его родителю и т. Д., Пока вы не попадете в загрузчик класса начальной загрузки. Если ни один из них не находит ссылку на класс, который вы пытаетесь загрузить, вы получаете ClassNotFoundException.
Если у вас есть два класса с одинаковыми двоичными именами, доступные для поиска одним и тем же загрузчиком классов, и вы хотите узнать, какой из них вы загружаете, вы можете проверить только то, как конкретный загрузчик классов пытается разрешить имя класса.
Согласно спецификации языка Java, для двоичного имени класса нет ограничения уникальности, но, насколько я вижу, оно должно быть уникальным для каждого загрузчика классов.
Я могу найти способ загрузки двух классов с одинаковыми двоичными именами, и он предполагает их загрузку (и все их зависимости) с помощью двух разных загрузчиков классов, переопределяющих поведение по умолчанию. Грубый пример:
ClassLoader loaderA = new MyClassLoader(libPathOne);
ClassLoader loaderB = new MyClassLoader(libPathTwo);
Object1 obj1 = loaderA.loadClass("first.class.binary.name", true)
Object2 obj2 = loaderB.loadClass("second.class.binary.name", true);
Я всегда считал настройку загрузчика классов сложной задачей. Я предпочел бы по возможности избегать множественных несовместимых зависимостей.
Автор: Luca Putzu Размещён: 24.05.2011 09:0720 плюса
Каждый класс выбирает ровно один класс. Обычно первый найден.
OSGi стремится решить проблему нескольких версий одной и той же банки. Equinox и Apache Felix являются общими реализациями с открытым исходным кодом для OSGi.
Автор: Tarlog Размещён: 24.05.2011 08:156 плюса
Classloader загрузит классы из фляги, которая сначала оказалась в пути к классам. Обычно несовместимые версии библиотеки имеют различия в пакетах, но в маловероятном случае они действительно несовместимы и не могут быть заменены на один - попробуйте jarjar.
Автор: Alex Gitelman Размещён: 24.05.2011 02:426 плюса
Загрузчики классов загружают класс по требованию. Это означает, что класс, требуемый сначала вашим приложением и связанными библиотеками, будет загружен раньше других классов; Запрос на загрузку зависимых классов обычно выдается во время процесса загрузки и связывания зависимого класса.
Вы, вероятно, столкнетесь LinkageError
с сообщением о том, что для загрузчиков классов встречаются повторяющиеся определения классов, которые обычно не пытаются определить, какой класс должен быть загружен первым (если в пути к классам загрузчика присутствуют два или более классов с одинаковым именем). Иногда загрузчик классов загружает первый класс, встречающийся в пути к классам, и игнорирует дублирующиеся классы, но это зависит от реализации загрузчика.
Рекомендуемая практика для устранения ошибок такого рода заключается в использовании отдельного загрузчика классов для каждого набора библиотек, имеющих конфликтующие зависимости. Таким образом, если загрузчик классов попытается загрузить классы из библиотеки, зависимые классы будут загружены тем же загрузчиком классов, который не имеет доступа к другим библиотекам и зависимостям.
Автор: Vineet Reynolds Размещён: 24.05.2011 03:130 плюса
Вы можете использовать команду URLClassLoader
for require для загрузки классов из версии jar diff-2:
URLClassLoader loader1 = new URLClassLoader(new URL[] {new File("httpclient-v1.jar").toURL()}, Thread.currentThread().getContextClassLoader());
URLClassLoader loader2 = new URLClassLoader(new URL[] {new File("httpclient-v2.jar").toURL()}, Thread.currentThread().getContextClassLoader());
Class<?> c1 = loader1.loadClass("com.abc.Hello");
Class<?> c2 = loader2.loadClass("com.abc.Hello");
BaseInterface i1 = (BaseInterface) c1.newInstance();
BaseInterface i2 = (BaseInterface) c2.newInstance();
Автор: Pankaj Kalra
Размещён: 24.04.2019 05:21
Вопросы из категории :
- java В чем разница между int и Integer в Java и C #?
- java Как я могу определить IP моего маршрутизатора / шлюза в Java?
- java Каков наилучший способ проверки XML-файла по сравнению с XSD-файлом?
- java Как округлить результат целочисленного деления?
- java Преобразование списка <Integer> в список <String>
- jar Как я должен загружать Jars динамически во время выполнения?
- jar Каков наилучший способ распространения приложений Java?
- jar Просмотр содержимого файла .jar
- jar Как получить путь к работающему файлу JAR?
- jar Как использовать файл в банке как javax.net.ssl.keystore?
- classpath Как установить длинный путь к классам Java в Windows?
- classpath Включение всех jar-файлов в каталог внутри Java classpath
- classpath В чем разница между CLASSPATH "записями начальной загрузки" и "записями пользователей" в Eclipse?
- classpath Как добавить каталог в classpath в профиле запуска приложения в IntelliJ IDEA?
- classpath Использование внешних файлов свойств в weblogic
- classloader Сканирование аннотаций Java во время выполнения
- classloader Ресурс Java как файл
- classloader URL для загрузки ресурсов из пути к классам в Java
- classloader Есть ли способ узнать, какие классы загружен ClassLoader?