已解析的 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 package
在 META-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 中包含的任何包或 类 都没有在我从异常中收到的堆栈跟踪中直接提到。
我正在维护的软件解决方案有点问题。我们之前已将整个解决方案从 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 package
在 META-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 中包含的任何包或 类 都没有在我从异常中收到的堆栈跟踪中直接提到。