2013-04-12 3 views
4

У меня есть два Java-проекта Test1 и Test2. Test1 имеет библиотеку lib, добавленную к ней в Eclipse Java Build Path. Test2 имеет добавленную банку в своем пути сборки.Как решить более глубокую версию jar-hell?

Test1  Test2 
/src  /src 
lib   Referenced Libraries 
x-1.1.jar a.jar 
y.jar  x-1.2 
       z 

Код в Test1 вызывает функции/классы y.jar, который зависит от x-1.1.jar. Я не знаю, какие функции/классы x-1.1.jar используются y.jar, поскольку у меня нет источника для банок. Аналогично Test2 вызывает функции/классы пакета z a.jar, которые имеют зависимость от x-1.2 verion jar.

Теперь у меня есть проект теста, где мне нужен как проекты Test1 и Test2

Test 
/src 
Test1 code 
Test2 code 
some other code which uses Test1 as well as Test2 libraries 
lib 
x-1.1.jar 
y.jar 
Referenced Libraries 
a.jar 
    x-1.2 
    z 

Теперь, когда я запускаю тестовый проект, я получаю в банке-ад ситуацию. Два подхода, используемый здесь мое исследование являются:

  1. Classpath: Проблема с этим подходом является то, что так как в библиотеке/банки для Test1, Test2 добавляются в затмении Java Build Path, только первую загруженную версию х .jar, и код Test2 ломается даже при использовании загрузчика классов.
  2. osgi: Проблема с подходом заключается в том, что я могу экспортировать только пакеты в папку src из Test1 и Test2 из пакета osgi, а не из тех, на которые ссылается проект. Но в тестовом проекте есть код, который использует библиотеки Test1 и Test2.

Надеюсь, что я достаточно ясен. Любая помощь приветствуется. Заранее спасибо.

Добавление дополнительной информации на вопрос: Мне нужно использовать два разных java-sdks в моем проекте, в которые были добавлены различные файлы jar. Конфликтующими являются:

jar file      Test1 ver Test2 ver 
org.apache.commons.codecs 1.3  1.6 
org.apache.commons.logging 1.1.1  1.1.1 
org.apache.log4j    1.2.7  1.2.15 
httpclient     4.1.1  4.0.3 
httpcore      4.1  4.1.4 

Какие могут быть возможные способы сделать это?

+2

OSGi: вы можете просто добавить иностранные пакеты в свой экспорт: http://stackoverflow.com/a/1235145/1165132 – Adrian

+1

Знаете ли вы * наверняка *, что 'x-1.2.jar' is * not * backward - совместим с 'x-1-1.jar'? Кроме того, вы можете использовать инструмент JDepend, чтобы узнать, какие функции использует один JAR из другого. – kdgregory

+0

Попробуйте bndtools ... –

ответ

0

Вы можете попытаться эмулировать разделение классов, как это делает OSGi, реализовав механизм загрузки пользовательского класса с двумя URLClassLoader s, по одному для каждого из x-1.*.jar.

Это общая идея:

File x1jar = new File("path/to/x-1.1.jar"); 
URLClassLoader x1loader = new URLClassLoader (x1ar.toURL(), this.getClass().getClassLoader()); 

File x2jar = new File("path/to/x-1.2.jar"); 
URLClassLoader x2loader = new URLClassLoader (x2ar.toURL(), this.getClass().getClassLoader()); 

// Test1 should look into x-1.1.jar .. 
Class test1class = Class.forName("Test1", true, x1loader); 

// .. Test2 should look into x-1.2.jar .. 
Class test2class = Class.forName("Test2", true, x2loader); 

// .. but both should see y.jar and z.jar via system class locader. 

// Invoke whatever methods in testXclasses. 

ВАЖЕН: x-1.1.jar и x-1.2.jar не должен быть в системе классов, то есть вы должны поместить их в отдельной lib папки, то есть развертывание класса должно выглядеть как это:

+ myapp 
    + lib 
    myapp.jar 
    y.jar 
    z.jar 
    + sandbox 
    x-1.1.jar 
    x-1.2.jar 

И вы не должны см Test1/Test2 непосредственно (с Test1 или Test1.class), только с именами классов (в строке "Test1").

Посмотрите на this answer и this one.

1

OSGI на самом деле, скорее всего, является решением, и у вас есть два способа сделать это:

  1. Преобразовать зависимые банки для OSGi расслоения, определяют, какие версии пакетов они делают экспорт (просто использовать реальные номера версий) эталонных (OSGI) из ваших тестовых проектов, при импорте пакетов укажите точные требуемые версии. Таким образом, вы создадите пакет osgi для каждой библиотеки и для каждого из ваших проектов.
  2. Создайте два пакета osgi: test1 и test2. Вставьте их нужную версию библиотек (как встроенные банки или встроенные) и не экспортируйте зависимые пакеты. Вы можете свободно ссылаться на test1 и test2 из тестового пакета. Они не будут сталкиваться, но будут находиться в изолированных загрузчиках классов (bundle classloader space). Информация о том, как встраивать зависимостей с использованием Maven пакет плагинов: http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html#ApacheFelixMavenBundlePlugin%28BND%29-EmbedDependencyandExportPackage

Акцент на этой конфигурации:

<Embed-Dependency> 
    *;scope=compile|runtime;inline=false 
</Embed-Dependency> 

Как обернуть банки для OSGi с помощью BND инструмент: http://java.dzone.com/articles/how-creategenerate-osgi

Кстати большинство (если не все) ваших упомянутых библиотек должны быть уже подготовлены osgi, поэтому вам даже не нужно будет преобразовывать их в пакеты osgi. Единственная проблема, которая может возникнуть здесь, заключается в том, что некоторые банки не совместимы с osgi (например, те, которые делают предположения о архитектуре загрузчика классов контейнера), но это очень редкий случай.

Смежные вопросы