使用BND構(gòu)建OSGi Bundle時(shí)如何只導(dǎo)出第三方依賴(lài)的包到MANIFEST.MF中而不解壓到j(luò)ar中?

本文是純第三方依賴(lài)的Eclipse插件的構(gòu)建和自動(dòng)更新的后續(xù)。

背景

之前構(gòu)建純第三方依賴(lài)的Eclipse插件的時(shí)候,通過(guò)Export-Package導(dǎo)出了不少包(例如apache commons、xstream、slf4j等)給其他插件使用,因?yàn)閷?dǎo)出包太多,導(dǎo)致Eclipse插件在查找類(lèi)的時(shí)候出現(xiàn)了性能問(wèn)題,所以現(xiàn)在想僅開(kāi)放必要的內(nèi)部包,公共組件的包由外部插件提供,一些必要的調(diào)用通過(guò)該插件內(nèi)部的代碼類(lèi)來(lái)提供。所以做了兩個(gè)修改:

  1. Export-Package中移除了公共組件的包,僅保留項(xiàng)目相關(guān)jar的包的導(dǎo)出。
  2. 代碼工程中增加了src/main/java源碼文件夾,通過(guò)自定義工具類(lèi)實(shí)現(xiàn)對(duì)插件內(nèi)部類(lèi)的配置。

經(jīng)過(guò)修改后重新打包,發(fā)現(xiàn)打包后的bundle jar中除了自定義的類(lèi)、第三方j(luò)ar之外,Export-Package中定義的導(dǎo)出包及其中的類(lèi)也被解壓到了bundle jar中,解壓后的包和class以及jar都存在于bundle jar中,這樣肯定是有問(wèn)題的。

問(wèn)題原因

通過(guò)查閱BND的資料,發(fā)現(xiàn)之前對(duì)Export-Package的理解有誤,之前一直以為該配置對(duì)應(yīng)的是Bundle MANIFEST.MF中的Export-Package,添加到該配置中的插件包及插件內(nèi)部jar中的包可以供外部插件訪(fǎng)問(wèn)。其實(shí)BND中的Export-Package并不僅僅是這個(gè)功能,先貼一段BND中的解釋說(shuō)明:

<Export-Package>
The <Export-Package> instruction is a list of packages for the bundle to export. These packages are copied into the resulting bundle JAR file from the available classes (i.e., project classes, dependencies, and class path); thus, it is possible to include classes into your bundle that are not associated with source files in your project. <Export-Package> can be specified with package patterns using the '*' wildcard. Also, it is possible to exclude packages using negation by starting the package pattern with '!'. Thus, non-negated patterns indicate which of the available packages to include in the bundle, whereas negated patterns indicate which should not be included in the bundle.

The list of package patterns is ordered and earlier patterns are applied before later patterns. For example, if you specify "org.foo.,!org.foo.impl" the second pattern has no effect since all org.foo packages have already been selected by the first pattern. Instead, you should specify "!org.foo.impl,org.foo.", which will export all org.foo packages except org.foo.impl.

Following standard OSGi R4 syntax, package patterns can include both directives and attributes, which will be copied appropriately into the generated Export-Package manifest header. Besides explicitly listing package version attributes, BND will also determine package versions by examining the source JAR file or from packageinfo files in the package directory.

注意上述說(shuō)明中的黑體部分。重點(diǎn)在第一段,第一段已經(jīng)說(shuō)明了添加到Export-Package中的包中的class會(huì)被復(fù)制到生成的bundle jar中,同時(shí)加入到MANIFEST.MF的Export-Package頭中。
但是我們之前構(gòu)建的bundle jar,并沒(méi)有將Export-Package包中的class復(fù)制到bundle jar中,是本次增加了src/main/java后才出現(xiàn)解壓class的現(xiàn)象,原因未知。

解決辦法

BND官網(wǎng)的常見(jiàn)問(wèn)題文檔中,第一條即是該問(wèn)題“當(dāng)我嵌入bundle中一個(gè)依賴(lài)時(shí)為什么我在bundle jar中看見(jiàn)了重復(fù)的類(lèi)?”,看來(lái)這個(gè)問(wèn)題比較普遍_。先來(lái)看BND給的解釋說(shuō)明:

Having two copies of classes, both unpacked and embedded as jars, is a sign that your Embed-Dependency and Export-Package instructions are overlapping. Export-Package tells BND to pull in classes found in the named packages from the build classpath and add them to the bundle, Embed-Dependency tells BND to embed (or inline if enabled) whole artifacts in the bundle.

BND的意思是如果你在最終的bundle jar中看見(jiàn)了重復(fù)的class和它所在的jar,說(shuō)明你在Embed-DependencyExport-Package中的定義重疊了。換句話(huà)說(shuō)就是,你同時(shí)配置了Embed-DependencyExport-Package,Export-Package將包中的class解壓到bundle jar,Embed-Dependency將jar復(fù)制到bundle jar中。
如果你僅僅是想在最終的bundle jar的MANIFEST.MF的Export-Package頭中導(dǎo)出包,并不想同時(shí)將包中的class解壓到bundle中,你需要使用<_exportcontents>替代Export-Package,具體做法:

  1. 移除<Export-Package>
  2. 在Embed-Dependency之后添加<_exportcontents>,例如:
<Embed-Dependency>*</Embed-Dependency>
<_exportcontents>org.apache.commons.*</_exportcontents>

參考資料

Apache Felix Bundle Plugin Frequently Asked Questions
使用BND構(gòu)建包含純第三方依賴(lài)的Eclipse插件

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容