4

我有两个 java 项目 Test1 和 Test2。Test1 在其 Eclipse Java Build Path 中添加了一个库库。Test2 在其构建路径中添加了一个 jar。

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

Test1 中的代码调用依赖于 x-1.1.jar 的 y.jar 的函数/类。我不知道 y.jar 使用了 x-1.1.jar 的哪些函数/类,因为我没有 jar 的来源。类似地,Test2 调用 a.jar 的 z 包的函数/类,这些函数/类依赖于 x-1.2 版本的 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 

现在,当我运行测试项目时,我陷入了 jar-hell 的境地。我的研究使用的两种方法是:

  1. 类路径:这种方法的问题在于,由于 Test1 和 Test2 的库/jar 都添加到了 eclipse Java 构建路径中,因此只能访问第一个加载的 x.jar 版本,并且即使使用类加载器,Test2 代码也会中断。
  2. osgi:方法的问题是我只能从 osgi 包中导出 Test1 和 Test2 的 src 文件夹中的包,而不是项目引用的包。但是 Test 项目的代码使用了 Test1 和 Test2 库。

希望我足够清楚。任何帮助是极大的赞赏。提前致谢。

在问题中添加更多信息:我必须在我的项目中使用两个不同的 java sdk,它们捆绑了不同的 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

有什么可能的方法来做到这一点?

4

2 回答 2

1

OSGI 实际上很可能是一种解决方案,您有两种方法可以做到:

  1. 将依赖的 jar 转换为 osgi 包,定义它们导出的包的版本(只需使用真实版本号)从您的测试项目中引用(OSGI 方式)它们,在导入包时指定确切的所需版本。这样,您将为每个库 jar 和每个项目创建 osgi 包。
  2. 创建两个 osgi 包:test1 和 test2。嵌入他们所需版本的库(作为嵌入式 jar 或内联),并且不导出依赖包。您可以从测试包中自由引用 test1 和 test2。它们不会发生冲突,但会驻留在隔离的类加载器(捆绑类加载器空间)中。有关如何使用 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>

如何使用 BND 工具将 jars 包装到 osgi:http: //java.dzone.com/articles/how-creategenerate-osgi

顺便说一句,您提到的大多数(如果不是全部)库应该已经准备好 osgi,因此您甚至不需要将它们转换为 osgi 包。这里可能出现的唯一问题是某些 jar 与 osgi 不兼容(例如那些对容器的类加载器架构做出假设的 jar),但这种情况很少见。

于 2013-07-24T15:01:14.947 回答
0

您可以尝试模拟类路径分离,就像 OSGi 所做的那样,通过实现具有两个URLClassLoaders 的自定义类加载机制,每个x-1.*.jars 一个。

这是一般的想法:

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直接(使用or )引用 Test1 / Test2 类Test1.class,只能使用类名(在 string 中"Test1")。

看看这个答案这个

于 2013-04-17T11:47:08.423 回答