OSGi/Equinox 类加载器使用了意外的捆绑版本
Posted
技术标签:
【中文标题】OSGi/Equinox 类加载器使用了意外的捆绑版本【英文标题】:OSGi/Equinox Classloader uses unexpected Bundle Version 【发布时间】:2012-09-10 14:36:05 【问题描述】:我有一个带有捆绑包的 OSGI 应用程序,需要 2 个版本的 IBM MQSeries: 6.0.2 和 7.0.1。 我们安装了以下 IBM MQ Bundle(仅提及主要的)
com.ibm.mq.osgi.client_6.0.2.5.jar
com.ibm.msg.client.osgi.wmq_7.0.1.5.jar
我们将 2 个 Bundle 定义为 Require-Bundle 如下(是的,我知道,我们应该使用 import-package ;-))
捆绑ARequire-Bundle: com.ibm.msg.client.osgi.wmq;bundle-version="7.0.1"
捆绑 B Require-Bundle: com.ibm.mq.osgi.client;bundle-version="[6.0.2,7.0.0)"
我们另外定义org.osgi.framework.bootdelegation=javax.*
。
没有伙伴类加载,没有动态类加载。
现在,当 Bundle A 加载 com.ibm.mq.jms.MQQueueConnectionFactory
使用
final MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();
我希望 Equinox 从 Bundle com.ibm.msg.client.osgi.wmq_7.0.1.5
加载类。
不是这种情况 !?!?? MQQueueConnectionFactory 是从 Bundle com.ibm.mq.osgi.client_6.0.2.5
加载的!!
因此,Bundle A 使用的是 MQ 6.0.2.5..
设置一些 Equinox Debug 选项,我可以看到以下内容:
Bundle id 56 == com.ibm.mq.osgi.client_6.0.2.5
Bundle id 53 == com.ibm.msg.client.osgi.jms.prereq_7.0.1.5
[...]
BundleLoader[A_1.1.3].loadBundleClass(com.ibm.mq.jms.MQQueueConnectionFactory)
BundleLoader[com.ibm.mq.osgi.client_6.0.2.5].findLocalClass(com.ibm.mq.jms.MQQueueConnectionFactory)
BundleClassLoader[PATH/org.eclipse.osgi/bundles/56/1/.cp/com.ibm.mq.jar].findClassImpl(com.ibm.mq.jms.MQQueueConnectionFactory)
BundleClassLoader[PATH/org.eclipse.osgi/bundles/56/1/.cp/com.ibm.mqjms.jar].findClassImpl(com.ibm.mq.jms.MQQueueConnectionFactory)
about to read 11659 bytes from com/ibm/mq/jms/MQQueueConnectionFactory.class
read 11659 bytes from PATH/org.eclipse.osgi/bundles/56/1/.cp/com.ibm.mqjms.jar/com/ibm/mq/jms/MQQueueConnectionFactory.class
defining class com.ibm.mq.jms.MQQueueConnectionFactory
[...]
“有趣”的部分是 javax.jms.* 类是从 com.ibm.msg.client.osgi.jms.prereq_7.0.1.5
加载的
BundleClassLoader[com.ibm.mq.osgi.client_6.0.2.5].loadClass(javax.jms.QueueConnectionFactory)
BundleLoader[com.ibm.mq.osgi.client_6.0.2.5].loadBundleClass(javax.jms.QueueConnectionFactory)
BundleLoader[com.ibm.msg.client.osgi.jms.prereq_7.0.1.5].findLocalClass(javax.jms.QueueConnectionFactory)
BundleClassLoader[PATH/org.eclipse.osgi/bundles/53/1/.cp/jms.jar].findClassImpl(javax.jms.QueueConnectionFactory)
about to read 371 bytes from javax/jms/QueueConnectionFactory.class
read 371 bytes from /opt/fxportal/FXMB/application/configuration/org.eclipse.osgi/bundles/53/1/.cp/jms.jar/javax/jms/QueueConnectionFactory.class
defining class javax.jms.QueueConnectionFactory
BundleLoader[com.ibm.msg.client.osgi.jms.prereq_7.0.1.5] found local class javax.jms.QueueConnectionFactory
恕我直言,这与 org.osgi.framework.bootdelegation
设置以及 7.0.1.5 JMS prereq 发生在 6.0.2.5 之前的事实有关。
有人可以解释捆绑类加载器的行为吗?为什么 Equinox 以这种方式连接束 A?我怎样才能达到预期的行为?
Bundle B 正在按预期工作...
【问题讨论】:
【参考方案1】:当我在 IDE 中使用 OSGi 相关编码时,我遇到了类似的情况。由您的 IDE 完成的这种接线是错误的。它从 com.ibm.mq.osgi.client_6.0.2.5
连接类,而您希望它连接同一类 com.ibm.msg.client.osgi.wmq_7.0.1.5
。在您谈到的第二个问题中,同样的问题正在发生。您可以通过查找 IDE 使用它的 com.ibm.mq.jms.MQQueueConnectionFactory
类来检查这一点。 (您可以使用 Ctrl + 鼠标单击查看已连接的版本)。
【讨论】:
【参考方案2】:如果这是一个有效的答案,请不要尝试在 BUndle A version="[7.0.1,7.0.1]" 中定义依赖项时使用此格式,这表示严格的版本范围。更糟糕的情况是,如果您仍然遇到问题,您可以通过执行 Platform.getBundle("com.ibm.msg.client.osgi.wmq").loadClass("com.myclass") 直接从 Bundle 加载类?
【讨论】:
以上是关于OSGi/Equinox 类加载器使用了意外的捆绑版本的主要内容,如果未能解决你的问题,请参考以下文章