OSGi类加载器问题

时间:2011-10-12 08:29:51

标签: osgi classloader

我是OSGi的新手。

我正在开发一个插件A(osgi包),假设依赖于库的 A ,假设 B-1.0 C-1.0 。现在如果库 C-1.0 依赖于库 B-2.0 (注意:不同版本的库 B )。所以我的插件在其类路径中有两个不同版本的库 B 。现在,我该如何处理这种情况?

由于我在过去4-5天内研究过OSGi,它为JIRA应用程序中的每个插件创建了一个类加载器,因此插件之间不会出现依赖版本不匹配。但是开发人员会做什么?如果插件本身需要两个不同版本的库jar?

我可以通过OSGi在单个osgi包中创建两个不同的类加载器,比如一个用于包X,另一个用于包Y吗?

请帮助我完成上述任何一种情况,或指出我正确的方向。

提前致谢。

3 个答案:

答案 0 :(得分:1)

请记住捆绑包不依赖于其他捆绑包 !!

其他捆绑包导出导出包。 (除非你使用过Require-Bundle,否则你不应该)。所以从你的例子中重新描述场景:

  • 捆绑 A 导入包org.foo。捆绑 C 导出包org.foo,OSGi将导入连接到导出。到目前为止一切顺利。

  • 捆绑 C 还会导入包org.bar。捆绑 B 1.0 导出包org.bar。因此,OSGi将这些连接在一起,一切都很好。

  • 现在......捆绑 A 还会导入包org.wibble。捆绑 B 2.0 导出包org.wibble。这也很好!就OSGi而言,捆绑 B 1.0 B 2.0 只是不同的捆绑包,它们都可以同时安装。

因此,当您按照实际工作方式查看依赖关系时,您会发现 A 完全可以导入来自两个不同版本的 B 的代码。但是有一个限制。请考虑以下事项:

  • 捆绑 D 导入包org.fooorg.bar v1.0(是的,包已版本化)。
  • 捆绑 E 导出包org.foo,以满足 D 中的导入。捆绑 E 还会导入包org.bar v2.0
  • 其他一些捆绑包(例如 F v1 F v2 )会导出org.bar个包的2个版本。

实际上这种情况仍然有效。 D 可以从某个地方导入包org.bar的1.0版本, E 可以从其他地方同时导入包org.bar的2.0版},同时正如 D E 导入包org.foo。我个人认为这非常不可思议!但如果org.foo“使用”org.bar,则无效,其中“使用”表示org.bar中的某些类型在org.foo的API中可见。在这种情况下,捆绑 D 会暴露给2个不同的副本org.bar,这是不允许的,因此OSGi会阻止捆绑 D 运行,因为不允许它进入RESOLVED或ACTIVE状态。

答案 1 :(得分:0)

在osgi包或插件中你将拥有meta-inf flie,它将定义你导入哪些类,如果你传递额外的agrument版本= 2.0,那么如果你没有指定任何东西它将使用B-2.0中的类然后它将解析为首先由classloader加载的那个。

即。 import-package(C 1.0): b.some.package; version =“2.0”或b.some.package;版本= “[2.0,4.0)”

import-package(A 1.0): b.some.package; version =“1.0”或b.some.package;版本= “1.0”

希望这有帮助

阿努普

答案 2 :(得分:0)

由于每个OSGi包都有自己的类加载器,运行时将有4个包,还有4个类加载器(A,B-1.0,B-2.0,C-1.0)。

B中可能包含两个相同类的副本(一个来自1.0,另一个来自2.0)。如果你运行它,你可能只是在A代码中遇到ClassCastException,因为两个版本的B类不一样。

OSGi提供"使用"条款提前检测这种情况。例如,C可能有如下的uses子句:

Export-Package: c.some.package;uses="b.some.package";version="1.0"
Import-Package: b.some.package;version="2.0"

在这种情况下,您将遇到早期失败(在解析A时),称为使用冲突,因为C会将其使用者的约束放在可接受的B版本上。

从概念上讲,解决此问题的唯一方法是让B的消费者(在这种情况下为A和C)同意B的版本。