Karaf开发中的Package uses conflict问题解决思路

编程技术  /  houtizong 发布于 3年前   387

问题现象

   目前在OSGi环境中记录log日志有很多选择,用的最多的应该是slf4j,针对slf4j的增强也很多,像eclipse/equinox环境中采用logback,karaf中采用pax-logging。

   因为没有注意到pax-logging-api的bundle里导出了org.slf4j(包括多个版本),我在karaf(karaf运行时采用pax-logging-api)中碰到org.slf4j.impl的package use conflict异常,如下:

Unable to execute command on bundle 100: The bundle"slf4j.api_1.7.5 [100]" could not be resolved. Reason: Package usesconflict: Import-Package: org.slf4j.impl; version="1.7.0"

此时我的bundle列表如下:

 

21 | Active    |   8 | 1.7.1                  | OPS4J Pax Logging - API100 | Installed |  30 | 1.7.5                  | slf4j-api                                                        101 | Installed |  30 | 1.7.5                  | jul-to-slf4j                                                     102 | Active    |  30 | 1.0.13                 | Logback Classic Module                                           103 | Active    |  30 | 1.0.13                 | Logback Core Module         

 

 

问题产生原因

    在我的系统里,karaf因为集成了eclipse virgo项目,所以log服务bundle包括pax-logging、logpack和slf4j都出现了,正是因为这样,才产生了package冲突问题。

关于包冲突的根源解释请参考OSGi规范和这篇Diagnosing OSGi uses conflicts文章。

    简单理解如下:

    系统中存在多个bundle(b1、b2)导出相同的package包A,同时bundle(b3)要导入相同名称的包A,OSGi框架在解析时,第一解析到的导出包A的bundle(b1)如果其导入也已经满足,即处于Resolved状态,则后续的bundle(b3)导入包A时,优先导入b1导出的包A。此时,如果bundle(b3)导出包B,而包B需要use包A,则其他bundle(b5)需要导入b2的包A,同时也导入包B时,将产生包冲突。

 

在karaf下解决问题的办法

    知道了问题产生的原因,现在整理解决思路:第一步,找到导出org.slf4j.impl的bundle,找到导入org.slf4j.impl的bundle;第二步,确定各个相关bundle导入导出的版本;第三步,解决具体问题。

    首先,看第一步,在karaf的命令行输入:

package:exports

输出如下:

 

……org.slf4j.bridge                                                 | 1.7.5          | 101 | jul.to.slf4j                                      org.slf4j.helpers                                                | 1.4.3          | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j.helpers                                                | 1.5.11         | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j.helpers                                                | 1.6.6          | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j.helpers                                                | 1.7.1          | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j.helpers                                                | 1.7.5          | 100 | slf4j.api                                         org.slf4j.impl                                                   | 1.7.5          | 102 | ch.qos.logback.classic                            org.slf4j.spi                                                    | 1.4.3          | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j.spi                                                    | 1.5.11         | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j.spi                                                    | 1.6.6          | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j.spi                                                    | 1.7.1          | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j.spi                                                    | 1.7.5          | 100 | slf4j.api                                         org.slf4j                                                        | 1.4.3          | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j                                                        | 1.5.11         | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j                                                        | 1.6.6          | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j                                                        | 1.7.1          | 21  | org.ops4j.pax.logging.pax-logging-api             org.slf4j                                                        | 1.7.5          | 100 | slf4j.api                                         ……

 

 

    从导出列表中可以看到,导出org.slf4j.impl的bundle只有ch.qos.logback.classic,而导出org.slf4j的有两个bundle,分别是pax-logging-api和slf4j.api。

    现在看导入,在karaf命令行输入:

package:imports

    输出如下:

 

(&(osgi.wiring.package=org.slf4j)(&(version>=1.5.0)(!(version>=2.0.0))))                                                             |          | 37  | org.apache.aries.blueprint.cm                       | true      (&(osgi.wiring.package=org.slf4j)(&(version>=1.6.0)(!(version>=2.0.0))))                                                             |          | 23  | org.apache.mina.core                                | true      (&(osgi.wiring.package=org.slf4j)(&(version>=1.7.0)(!(version>=2.0.0))))                                                             |          | 123 | org.eclipse.virgo.kernel.model                      | true      (&(osgi.wiring.package=org.slf4j)(version>=1.5.0))                                                                                   |          | 53  | org.ops4j.pax.url.commons                           | true      (&(osgi.wiring.package=org.slf4j)(version>=1.7.0))                                                                                   |          | 102 | ch.qos.logback.classic                              | true      (&(osgi.wiring.package=org.slf4j)(version>=1.7.5))                                                                                   |          | 101 | jul.to.slf4j                                        | true      (&(osgi.wiring.package=org.slf4j))                                                                                                   | optional | 127 | org.apache.felix.http.jetty                         | true      (&(osgi.wiring.package=org.slf4j.bridge)(&(version>=1.7.0)(!(version>=2.0.0))))                                                      |          | 105 | org.eclipse.virgo.medic.core                        | true      (&(osgi.wiring.package=org.slf4j.helpers)(&(version>=1.7.0)(!(version>=2.0.0))))                                                     |          | 105 | org.eclipse.virgo.medic.core                        | true      (&(osgi.wiring.package=org.slf4j.helpers)(version>=1.7.0))                                                                           |          | 102 | ch.qos.logback.classic                              | true      (&(osgi.wiring.package=org.slf4j.impl)(version>=1.7.0))                                                                              |          | 102 | ch.qos.logback.classic                              | true      (&(osgi.wiring.package=org.slf4j.spi)(version>=1.7.0))                                                                               |          | 102 | ch.qos.logback.classic                              | true      (&(osgi.wiring.package=org.slf4j.spi)(version>=1.7.5))                                                                               |          | 101 | jul.to.slf4j                                        | true  

 

 

    从导入看,logback.classic在导出org.slf4j.impl的同时需要导入org.slf4j。因slf4j.api处于Installed状态无法看到其导入。

   查看slf4j.api的bundle头信息,在karaf命令行输入:

Bundle:headers 100

输出如下:

 

Bundle-Name = slf4j-apiBundle-Description = The slf4j APIBundle-SymbolicName = slf4j.apiBundle-Version = 1.7.5Bundle-ManifestVersion = 2 Import-Package =org.slf4j.impl;version=1.6.0Export-Package =org.slf4j;version=1.7.5,org.slf4j.spi;version=1.7.5,org.slf4j.helpers;version=1.7.5

 

 

    查看logback.classic的bundle头信息,输出如下:

 

org.slf4j.impl;uses:="org.slf4j.spi,ch.qos.logback.core.status,ch.qos.logback.classic.util,org.slf4j.helpers,ch.qos.logback.classic,ch.qos.logback.core,ch.qos.logback.classic.selector,ch.qos.logback.core.joran.spi,org.slf4j,ch.qos.logback.core.util";version=1.7.5

 

 

    通过上述诊断,结合包冲突的原理,可以看出,

       1)pax-logging-api在karaf中优先级别高于slf4j.api,此时OSGi框架已经识别到org.slf4j包;

       2)在解析slf4j.api时,因slf4j.api需要导入org.slf4j.impl,而其之前没有bundle导出slf4j.impl,所以其解析状态不能变为Resolved;

       3)当解析到logback.classic时,此bundle导出了slf4j.impl,但其同时use包org.slf4j,因此logback.classic优先导入pax-logging-api导出的org.slf4j包。

 

       4)此时在其解析slf4j.api时,slf4j.api本身导出的org.slf4j与其导入org.slf4j.impl所在的logback.classic所导入的pax logging中的org.slf4j冲突。

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

留言需要登陆哦

技术博客集 - 网站简介:
前后端技术:
后端基于Hyperf2.1框架开发,前端使用Bootstrap可视化布局系统生成

网站主要作用:
1.编程技术分享及讨论交流,内置聊天系统;
2.测试交流框架问题,比如:Hyperf、Laravel、TP、beego;
3.本站数据是基于大数据采集等爬虫技术为基础助力分享知识,如有侵权请发邮件到站长邮箱,站长会尽快处理;
4.站长邮箱:[email protected];

      订阅博客周刊 去订阅

文章归档

文章标签

友情链接

Auther ·HouTiZong
侯体宗的博客
© 2020 zongscan.com
版权所有ICP证 : 粤ICP备20027696号
PHP交流群 也可以扫右边的二维码
侯体宗的博客