OSGi 类加载器问题
我对 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 ?
请在上述任何情况下帮助我或为我指明正确的方向。
提前致谢。
I am very new to OSGi.
I am developing a plugin A (osgi bundle), suppose A which depends on libraries, suppose B-1.0 and C-1.0. Now If the library C-1.0 depends on library B-2.0 (Note: the different version of library B). So my plugin has two different versions of the library B in its classpath. Now, How can I handle this situation ?
As I am studying from last 4-5 days about OSGi that it creates a classloader for each plugin in the JIRA application, so that dependency version mismatch do not occur between plugins. But What would a developer do If a plugin itself needs two different versions of a library jar ?
Can I create two different classloaders in a single osgi bundle through OSGi, say one for package X and another one for package Y ?
Please help me in any of the above scenarios or point me to the right direction.
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
请记住捆绑包不依赖于其他捆绑包!
捆绑包导入由其他捆绑包导出的包。 (除非您使用过 Require-Bundle,但您不应该使用)。因此,要重新表述示例中的场景:
Bundle A 导入包
org.foo
。 Bundle C 导出包org.foo
,OSGi 将导入连接到导出。到目前为止一切顺利。Bundle C 还导入包
org.bar
。捆绑包 B 1.0 导出包org.bar
。因此,OSGi 将它们连接在一起,一切都很好。现在...bundle A 还导入包
org.wibble
。捆绑包 B 2.0 导出包org.wibble
。这也好啊!就 OSGi 而言,捆绑包 B 1.0 和 B 2.0 只是不同的捆绑包,它们可以同时安装。因此,当您查看依赖项的实际工作方式时,您会发现 A 完全有可能导入来自两个不同版本的 B 的代码。但有一个限制。请考虑以下情况:
org.foo
和org.bar v1.0
(是的,包是有版本的)。org.foo
,满足 D 中的导入。 Bundle E 还导入包org.bar v2.0
。org.bar
软件包。其实这个场景还是可以的。 D 可以从某处导入包
org.bar
的 1.0 版本,E 可以导入包org.bar
的 2.0 版本code> 从其他地方导入,同时 D 正在从 E 导入包org.foo
。我个人觉得这非常不可思议!但如果org.foo
“使用”org.bar
,则不起作用,其中“uses”意味着org.bar
中的某些类型是在org.foo
的 API 中可见。在这种情况下,捆绑包 D 将暴露给 2 个不同的副本org.bar
,这是不允许的,因此 OSGi 将阻止捆绑包 D通过不允许其进入 RESOLVED 或 ACTIVE 状态来运行。Remember that bundles do not depend on other bundles!!
Bundles import packages that are exported by other bundles. (unless you have used
Require-Bundle
, but you should not). So to rephrase the scenario from your example:Bundle A imports package
org.foo
. Bundle C exports packageorg.foo
, and OSGi wires the import to the export. So far so good.Bundle C also imports package
org.bar
. Bundle B 1.0 exports packageorg.bar
. Therefore OSGi wires these together and everything is still fine.Now... bundle A also imports package
org.wibble
. Bundle B 2.0 exports packageorg.wibble
. This is fine as well! Bundles B 1.0 and B 2.0 are simply different bundles as far as OSGi is concerned, they can both be installed at the same time.So when you look at the dependencies the way they actually work, you find that it's perfectly possible for A to import code that comes from two different versions of B. However there is a limitation. Consider the following:
org.foo
andorg.bar v1.0
(yes, packages are versioned).org.foo
, which satisfies the import in D. Bundle E also imports packageorg.bar v2.0
.org.bar
packages.Actually this scenario can still work. D can import version 1.0 of package
org.bar
from somewhere, and E can import version 2.0 of packageorg.bar
from somewhere else, at the same time as D is importing packageorg.foo
from E. I personally find this pretty incredible! But it does not work iforg.foo
"uses"org.bar
, where "uses" means that some types inorg.bar
are visible in the API oforg.foo
. In this case, bundle D would be exposed to 2 different copiesorg.bar
, which is not allowed, so OSGi will prevent bundle D from running by not allowing it to enter RESOLVED or ACTIVE states.在osgi包或插件中,你将有meta-inf flie,它将定义你导入的类,如果你传递额外的参数是版本= 2.0,那么它将使用B-2.0中的类,如果你没有指定任何东西,那么它'将解析为首先由类加载器加载的一个。
IE
导入包(C 1.0):
b.一些.package; version="2.0" 或 b.some.package;版本=“[2.0,4.0)”
导入包(A 1.0):
b.一些.package; version="1.0" 或 b.some.package; version="1.0"
希望这对
Anup有帮助
In osgi bundle or plugin you'll have meta-inf flie which will define which classes you import if you pass extra agrument being the version=2.0 then it will use the class from B-2.0 if you don't specify anything then it'll resolve to one that is loaded by classloader first.
i.e.
import-package(C 1.0):
b.some.package; version="2.0" or b.some.package; version="[2.0,4.0)"
import-package(A 1.0):
b.some.package; version="1.0" or b.some.package; version="1.0"
Hope this helps
Anup
由于每个 OSGi 包都有自己的类加载器,因此运行时中将有 4 个包,还有 4 个类加载器(A、B-1.0、B-2.0、C-1.0)。
B 中可能包含同一类的两份副本(一份来自 1.0,另一份来自 2.0)。如果运行此代码,您可能会在 A 代码中遇到 ClassCastException,因为 B 类的两个版本不相同。
OSGi 提供了一个“uses”子句来及早检测此类情况。例如,C 可能有如下的 uses 子句:
在这种情况下,您将遇到早期失败(在解析 A 时),称为使用冲突,因为 C 为其使用者设置了约束 从概念上讲
,解决此问题的唯一方法是让 B 的消费者(在本例中为 A 和 C)就 B 的版本达成一致。
Since each OSGi bundle has its own classloader, there will be 4 bundles in the runtime, and also 4 classloaders (A, B-1.0, B-2.0, C-1.0).
You may have two copies of the same class included in B (one from 1.0 and another from 2.0). If you run this, you may simply run into a ClassCastException in the A code because two versions of B classes are not the same.
OSGi provides a "uses" clause to detect this type of situations early. For example, C may have a uses clauses like the following:
In this case, you will have an earlier failure (while resolving A), known as a uses conflict, because C places a constraint for its consumer on an acceptable version of B.
Conceptually, the only way to fix this problem is to have consumers of B (A and C in this case) agree on the version of B.