【问题标题】:OSGi classloader issuesOSGi 类加载器问题
【发布时间】:2011-12-05 22:30:50
【问题描述】:

我对 OSGi 很陌生。

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

正如我从过去 4-5 天开始研究 OSGi 一样,它为 JIRA 应用程序中的每个插件创建了一个类加载器,因此插件之间不会发生依赖版本不匹配的情况。但是如果一个插件本身需要两个不同版本的库 jar,开发者会怎么做呢?

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

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

提前致谢。

【问题讨论】:

  • 感谢大家的解决方案,非常抱歉我迟到的回复,但您提供的解决方案假定这些都是 OSGi 捆绑包。好的,让我重新表述我的问题,我的问题是我只有一个 OSGi 包 Plugin A 并且所有其他都是简单的库,而不是 OSGi 包。单个 OSGi 包如何将库 B-1.0 用于其包之一,例如 com.example.foo 并使用库 B-2.0 用于另一个包说 com.example.bar。 (这就是为什么我要在一个 OSGi 包中创建两个不同的类加载器。)

标签: osgi classloader


【解决方案1】:

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

捆绑导入包被其他捆绑导出。 (除非你使用过Require-Bundle,但你不应该使用)。因此,从您的示例中重新表述该场景:

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

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

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

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

  • Bundle D 导入包 org.fooorg.bar v1.0(是的,包是版本化的)。
  • Bundle E导出包org.foo,满足D中的导入。 Bundle E 还导入包org.bar v2.0
  • 其他一些捆绑包(例如 F v1F 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中是可见的。在这种情况下,bundle D 将暴露给 2 个不同的副本 org.bar,这是不允许的,因此 OSGi 将通过不允许 bundle D 进入来阻止它运行RESOLVED 或 ACTIVE 状态。

【讨论】:

    【解决方案2】:

    在 osgi 包或插件中,您将拥有 meta-inf flye,如果您传递额外的 agrument 为 version=2.0,它将定义您导入的类,如果您不指定任何内容,它将使用 B-2.0 中的类然后它将解析为首先由类加载器加载的。

    即 导入包(C 1.0): b.some.package; version="2.0" 或 b.some.package;版本="[2.0,4.0)"

    导入包(A 1.0): b.some.package; version="1.0" 或 b.some.package;版本="1.0"

    希望对你有帮助

    阿努普

    【讨论】:

      【解决方案3】:

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

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

      OSGi 提供了一个“uses”子句来及早检测到这种情况。例如,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 的版本达成一致。

      【讨论】:

        猜你喜欢
        • 2011-08-05
        • 1970-01-01
        • 2012-07-27
        • 2012-07-08
        • 2014-09-04
        • 2017-11-04
        • 1970-01-01
        • 2012-01-10
        • 2016-07-13
        相关资源
        最近更新 更多