目的:Eclipse插件開發(fā)中,經(jīng)常要引用第三方包或者是引用其他插件中的類,由于插件開發(fā)環(huán)境引用類路徑的設(shè)置和運(yùn)行平臺(tái)引用類路徑的設(shè)置不同,經(jīng)常導(dǎo)致開發(fā)過程OK,一旦運(yùn)行則出現(xiàn)NoClassDefFoundError的問題。本文的目的是全面分析各種情況下類路徑的設(shè)置,以避免這個(gè)問題的出現(xiàn)。
說明:Jar包和類路徑實(shí)際上是一個(gè)概念,比如類com.bbebfe.Test.class打包為test.jar包,添加類引用就直接添加test.jar包。而如果是添加類文件路徑,則添加包目錄的上級(jí)目錄,比如lib/com/bbebfe/Test.class,則添加lib文件夾,而不是com文件夾。在此后的例子中都只說明Jar包的形式。
分析:Eclipse插件開發(fā)對(duì)于Jar包的引用主要有三種原因:
1. 插件引用第三方包(普通的jar包或者類文件,不是插件)。
a) 開發(fā)環(huán)境引用配置,在prject -> properties -> Java build path中設(shè)置。
b) 運(yùn)行環(huán)境引用配置,在plugin manifest編輯器的Runtime選項(xiàng)卡下的classpath中添加tset.jar包的引用(在MANIFEST.MF中表現(xiàn)為Bundle-ClassPath: lib/test.jar, 在plugin.xml表現(xiàn)為<runtime>節(jié)下的引用
i. 類文件在lib目錄下,如下的設(shè)置導(dǎo)出lib目錄下所有目錄:
<runtime>
<library name="lib/">
<export name="*"/>
</library>
</runtime>
ii. test.jar在lib目錄下:
<runtime>
<library name="lib/test.jar">
<export name="*"/>
</library>
</runtime>
iii. 實(shí)際上上面的設(shè)置可以簡(jiǎn)化為:
<runtime>
<library name="lib/"/>
</runtime>
或者
<runtime>
<library name="lib/test.jar"/>
</runtime>
默認(rèn)即導(dǎo)出lib目錄下的所有包和jar下的所有包
實(shí)際上,執(zhí)行b)項(xiàng)設(shè)置后,會(huì)自動(dòng)執(zhí)行a)項(xiàng)設(shè)置,使開發(fā)環(huán)境和運(yùn)行環(huán)境同時(shí)有效。
2. 插件B引用插件工程A(非Eclipse插件,而是自己另外一個(gè)插件項(xiàng)目中的類)
a) 首先必須將A中的B需要的類暴露(export)出來
i. 如果有MANIFEST.MF文件,則表現(xiàn)為plugin manifest編輯器中runtime節(jié)的exported packages,通過這里添加需要export的包。在manifest.mf文件中是Export-Package: com.bbebfe
ii. 如果只有plugin.xml,則表現(xiàn)為plugin manifest編輯器中runtime節(jié)的library visibility。在plugin.xml文件中表現(xiàn)為
<runtime>
<library>
<export name=”com.bbebfe.*”/>
...
b) 在B插件工程的plugin manifest編輯器中的dependencies選項(xiàng)卡中添加對(duì)A插件的引用(這要求運(yùn)行對(duì)話框中的plugins列表的workspace plugins中必須包含A插件)。
c) 如果B工程是一個(gè)RCP工程,則必須在product編輯器的configuration選項(xiàng)卡中包含A插件工程。
3. 插件B引用Eclipse插件A的類。
a) Eclipse插件中的類都是Exported,因此這步省略。
b) 在B插件工程的plugin manifest編輯器中的dependencies選項(xiàng)卡中添加對(duì)A插件的引用(這要求preferences -> plugin development -> target目標(biāo)平臺(tái)必須包含A插件,且運(yùn)行對(duì)話框的plugins列表中的target platform中必須選中A插件)。
總結(jié):如果B插件引用的A也是一個(gè)插件,則A必須出現(xiàn)在B插件的plugin dependencies引用中,而不是其他地方,否則肯定會(huì)出現(xiàn)運(yùn)行時(shí)NoClassDefFoundError問題(因此必須在plugin manifest編輯器的dependencies選項(xiàng)卡下進(jìn)行設(shè)置)。而且只需要在這里設(shè)置的設(shè)置對(duì)開發(fā)環(huán)境和運(yùn)行環(huán)境同時(shí)有效)
注意:還有一種情況就是開發(fā)環(huán)境沒有某個(gè)包或者插件,而只在運(yùn)行環(huán)境(target)中存在,此時(shí)就必須設(shè)置正確的target,然后按照正常程序添加插件引用,但此時(shí)已經(jīng)不能在plugin manifest的dependencies選項(xiàng)卡中設(shè)置(因?yàn)樵陂_發(fā)環(huán)境找不到這個(gè)plugin),而必須在plugin.xml或MANIFEST.MF文件中手工設(shè)置。plugin只要target中存在該插件,則開發(fā)和運(yùn)行也不會(huì)有問題。