2011-10-12 77 views
1

我对OSGi非常陌生。OSGi类加载器问题

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

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

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

请帮助我在上述任何情况下或指向正确的方向。

在此先感谢。

+0

感谢所有您的解决方案,并非常抱歉我的迟交回复,但您提供的解决方案假定这些全部都是OSGi捆绑包。好的,让我重述一下我的问题,我的问题是我只有一个OSGi捆绑软件**插件A **,其他都是简单的库,而不是OSGi捆绑软件包。一个单独的OSGi包如何使用库** B-1.0 **作为它的一个包说** com.example.foo **并且使用库** B-2.0 **作为另一个包说** com.example。酒吧**。 (这就是为什么我要求在一个OSGi包中创建两个不同的类加载器。) –

回答

0

在osgi包或插件中,如果您传递的是额外的版本= 2.0,那么它将定义导入哪些类,如果您未指定,则它将使用B-2.0中的类任何东西,然后它会解析到一个由classloader首先加载的。

即 进口包装(C 1.0): b.some.package; version =“2.0”或b.some.package;版本=“[2.0,4.0)”

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

希望这有助于

阿努普

0

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

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

OSGi提供了一个“用法”子句来尽早检测这种情况。例如,C可以有使用类似的条款如下:

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的版本

1

记住捆绑不依赖于其他捆绑

进口包出口由其他包。 (除非你使用Require-Bundle,但你不应该)。所以,从你的例子改写的场景:

  • 捆绑一个进口包装org.foo。捆绑C出口包org.foo,和OSGi导入导出到出口。到现在为止还挺好。

  • Bundle C也进口包org.bar。包B 1.0出口包org.bar。因此OSGi将这些连接在一起,一切都很好。

  • 现在...捆绑A也进口包org.wibble。套装B 2.0出口包装org.wibble。这也很好! Bundles B 1.0 and B 2.0就OSGi而言只是简单的不同包,它们都可以同时安装。

所以,当你在依赖他们实际的工作方式,你会发现这是完全可能的一个导入来自两个不同的版本的代码。但是有一个限制。考虑以下几点:

  • 捆绑d进口包org.fooorg.bar v1.0(是的,包版本)。
  • 捆绑E出口包org.foo,满足进口D。包E也进口包org.bar v2.0
  • 某些其他软件包(说F v1F v2)导出org.bar包的2个版本。

实际上这种情况仍然可以工作。 d可以从某处导入包org.bar的1.0版,和Ë可以从其他地方如dË导入包org.foo导入包org.bar的2.0版,在同一时间。我个人觉得这很不可思议!但是,如果org.foo“使用”org.bar,则它不起作用,其中“使用”表示org.bar中的某些类型在org.foo的API中可见。在这种情况下,软件包D将暴露于2个不同的副本org.bar,这是不允许的,因此OSGi将通过不允许进入RESOLVED或ACTIVE状态来阻止软件包D运行。