6

OSGi 存在拆分包的问题,​​即同一个包但托管在多个包中。

是否存在拆分包可能会在纯 java(没有 OSGi)中造成问题的边缘情况?

只是好奇。

4

5 回答 5

14

拆分包的来源

拆分包(在 OSGi 中)在使用清单标头时发生Require-Bundle(我相信,在 Eclipse 的清单中)。Require-Bundle命名用于搜索类的其他包(如果未Import编辑包)。搜索发生在搜索捆绑包自己的类路径之前。这允许从多个包(可能是不同的 jar)的导出中加载单个包的类。

OSGi 规范 (4.1) 第 3.13 节描述Require-Bundle并列出了一长串使用此标头的(意外)后果(是否应弃用此标头?),其中一节专门用于拆分包。其中一些后果是奇怪的(而且是特定于 OSGi 的),但如果你了解一件事,大多数后果是可以避免的:

  • 如果一个(在一个包中)由多个包提供,那么你就有麻烦了。

如果包片段是不相交的,那么一切都应该很好,除了你可能没有在任何地方都可见类,并且如果从拆分包的“错误”部分查看包可见性成员可能看起来是私有的。

[当然这太简单了——可以安装多个版本的包——但是从应用程序的角度来看,任何时候一个包中的所有类都应该来自一个模块。]

“标准 Java”中会发生什么

在标准 Java 中,没有花哨的类加载器,您有一个类路径,并且为要加载的类搜索 jar(和目录)的顺序是固定且明确定义的:所得到的就是所得到的。(但是,我们放弃了可管理的模块化。)

当然,你可以拆分包——事实上这很常见——这表明模块化很差。症状可能是模糊的编译/构建时错误,但在多个类实现的情况下(一个覆盖单个类路径中的其余部分),由于语义略有不同,它通常会产生模糊的运行时行为.

如果你很幸运,你最终会在没有意识到的情况下查看错误的代码并问自己“但那怎么可能做到这一点?”
如果你不走运,你正在查看正确的代码并提出完全相同的问题——因为其他东西会产生意想不到的答案。

这与古老的数据库格言并不完全不同:“如果你在两个地方记录相同的信息,很快它就不再一样了”。我们的问题是“很快”通常不够快。

于 2009-05-19T12:02:02.537 回答
5

对于 OSGi 的包来说,不同的包是不同的,不管它们的名字是什么,因为每个包都使用自己的类加载器。确保捆绑包的封装不是问题,而是一个特性。

因此,在普通 Java 中,这通常不是问题,直到您开始使用一些使用类加载器的框架。这通常是加载组件时的情况。

于 2009-01-02T08:04:13.190 回答
3

跨 jar 拆分包可能不是一个好主意。我建议密封罐子中的所有包裹(放在"Sealed: true"清单的主要部分)。密封的包装不能在罐子之间分开。

对于 OSGi,具有相同包名但类加载器不同的类被视为位于不同的包中。

于 2009-01-02T12:10:43.087 回答
3

如果您在同一个包中有类并且有些类在已签名的 JAR 中,而另一些则不在,您将得到一个令人讨厌的运行时错误。

于 2009-01-02T14:16:55.267 回答
0

你问是因为有问题的包是你的,而不是第三方代码?

一个简单的例子是一个 Web 应用程序,它具有作为单独的 OSGi 包的服务和持久层。持久性接口必须由两个捆绑包共享。

如果我正确解释了您的问题,解决方案是创建一个包含共享接口的密封 JAR 并使其成为两个捆绑包的一部分吗?

我并不是要尝试劫持线程。我要求那些迄今为止可能比我在 OSGi 上做得更多的人进行澄清和提供一些更好的见解。

于 2009-01-02T14:11:50.160 回答