已解析的 OSGI 包上出现 ClassNotFoundException

ClassNotFoundException on resolved OSGI bundle

我正在维护的软件解决方案有点问题。我们之前已将整个解决方案从 Java 1.7 移至 Java 1.8,并且最终再次拥有大部分内容 运行。

现在我遇到了一个问题。在我构建的产品中,某个 class 似乎无法加载。这个 class 来自 jar 中的一个 bundle,它是调用 bundle 清单中的 required-Bundle。

奇怪的是,当启动 osgi 环境时,包似乎被解析了,所以我想 .jar 是正确找到的。但是,一旦程序尝试加载某个对话,我就会收到 ClassNotFoundException。

在我的 IDE 中,对话完美无缺,只是构建的产品似乎无法在 运行 时间加载 class(即使包含它的包解决)。

正在发生的事情的图形表示:

+-----------------------+   +---------------------------+
|xtext....jar           |   |MyProject                  |
|.                      |   |.                          |
|.                      |   |.                          |    +-------------------------+
|.                      |   | MANIFEST.MF               |    |ClassNotFoundException   |
|  MANIFEST.MF          +---> -Bundle-Name:MyBundle     +--->+at runtime in built      |
|  -Bundle-Name:X-Bundle|   | -Require-Bundle:X-Bundle  |    +version                  |
|  -Export-Package:x    |   |                           |    +-------------------------+
|.                      |   |                           |
|.                      |   +---------------------------+
|DeltaConverter.class   |
|                       |
+-----------------------+

在 运行 时在构建版本中找不到 class DeltaConverter,尽管捆绑包已解析并且我有一个使用它的捆绑包的要求捆绑包。

任何提示,这里可能发生了什么?

长话短说:

确保您的 classes packageMETA-INF/MANIFEST.MF 中导出。


长版:

即使捆绑包已解析并处于活动状态,也不意味着 class 在系统的其他捆绑包或部分中可用。

class所在的package必须导出。每个捆绑包都有一个 META-INF/MANIFEST.MF。这基本上就像一个捆绑包描述。

在该描述中有一个名为 Export-Package 的字段,其中包含所有导出的包的列表,因此可以在其他包中使用。

通常,META-INF/MANIFEST.MF 是在 Maven 构建过程中创建的,或者 Gradle 通过插件创建的。检查这些插件的配置或查看它们的工作方式。例如,某些插件不会导出低于 impl 个包的包。

因此,如果您 class 在包 com.example.awesomeapp.impl.services 中,则不会导出 service 包。但这取决于您使用的插件等

所有这些都适用于您的 IDE,因为它处理 class 路径的方式与您的 OSGi 环境不同。简而言之:您的 IDE 或多或少只知道一个包含所有 class 的 class 路径,而 OSGi 使用很多 class 路径(每个包一个和一对其他 class 路径),因此彼此 "hides" classes。这就是为什么您的 IDE 可以加载 class 而您的 OSGi 包不能。

现在好像可以了。当我试图解决一个我认为与这个问题无关的问题时,问题就消失了。我的构建服务器上有 2 个看似无关的 jar 文件(org.objectweb.asm_3.3.1 和 org.objectweb.asm_5.0.1)。该构建使用的是旧版本,然后我从构建服务器中删除了它,因此它只能使用较新的版本。 更改此设置后,现在一切似乎都可以正常工作,尽管我真的不明白为什么这可以解决问题。 奇怪的是,无论是这个 jar 还是这个 jar 中包含的任何包或 类 都没有在我从异常中收到的堆栈跟踪中直接提到。