本發(fā)明涉及計(jì)算機(jī)技術(shù)領(lǐng)域,尤其涉及一種共享對(duì)象庫(kù)加載的方法及裝置。
背景技術(shù):
在安卓(Android)開發(fā)中,可以通過(guò)Java本地接口(Java Native Interface,縮寫成JNI)的方式來(lái)調(diào)用和訪問(wèn)用C/C++實(shí)現(xiàn)的代碼,這些代碼以共享對(duì)象(SharedObject,縮寫成SO)文件的方式存在于共享對(duì)象庫(kù),即SO庫(kù)中。
當(dāng)Java層在調(diào)用本地(Native)層時(shí),有時(shí)會(huì)存在在預(yù)加載的SO庫(kù)中沒(méi)有找到要調(diào)用的SO文件而導(dǎo)致加載失敗的情況,雖然是低概率事件,但一旦加載失敗則會(huì)導(dǎo)致整個(gè)應(yīng)用崩潰。
現(xiàn)有技術(shù)中當(dāng)通過(guò)JNI接口加載SO庫(kù)中的例如以“l(fā)ib*.SO”表示的SO文件時(shí),如果加載不成功,則會(huì)采用異常處理try-catch的方式的跳到異常處理部分。
其中try-catch中的try可以保證程序的正常運(yùn)行,其用于捕獲程序的異常,而catch則用于輸出為什么出錯(cuò)。
采用try-catch的具體方式為:在try-catch的執(zhí)行過(guò)程中,首先逐個(gè)從上到下執(zhí)行try塊中的語(yǔ)句,如果沒(méi)有發(fā)生異常,則執(zhí)行完try塊后跳過(guò)catch塊。如果try塊中某條語(yǔ)句存在異常,則跳到相對(duì)應(yīng)的catch塊中,執(zhí)行完該catch塊中的語(yǔ)句,然后跳過(guò)其它的catch塊,接著往下走,其語(yǔ)句后面通常跟著語(yǔ)句finally,以提供一個(gè)統(tǒng)一的出口。
例如執(zhí)行下面的try-catch:
try{
int i=1/0;
}catch(Exception e){
........
}
如果try塊中計(jì)算“int i=1/0”除數(shù)為0,則跳到相對(duì)應(yīng)的catch塊中“Exception e”而報(bào)錯(cuò),如果沒(méi)有try的話,程序直接崩潰。用try的話,則可以讓程序運(yùn)行下去,并且輸出為什么出錯(cuò)。
現(xiàn)有技術(shù)中通過(guò)使用try-catch的方式,雖然可以在SO庫(kù)加載失敗時(shí)提示加載錯(cuò)誤,但其僅能夠發(fā)現(xiàn)問(wèn)題,并不能幫助有效的加載SO庫(kù)。
技術(shù)實(shí)現(xiàn)要素:
本發(fā)明的解決方案主要是保證能成功加載SO庫(kù),確保上層Java層調(diào)用本地Native層正常。具體為:
本發(fā)明提供了一種SO庫(kù)加載的方法和裝置,。
具體技術(shù)方案如下:
一種共享對(duì)象SO庫(kù)加載的方法,所述方法包括:
確定SO庫(kù)加載失敗的原因;
依據(jù)SO庫(kù)加載失敗的原因選擇以下加載方式之一加載SO庫(kù):
釋放并重新安裝包含所述SO庫(kù)的安裝包;
使用全路徑的方式或者使用文件加載的方式加載SO庫(kù);
使用文件鎖的方式保證僅多個(gè)進(jìn)程之一加載SO庫(kù)。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,如果確定SO庫(kù)加載失敗的原因是所述SO庫(kù)中的SO文件不存在、SO文件不完整、或者SO文件被篡改,則選擇所述釋放并重新安裝包含所述SO庫(kù)的安裝包的方式加載SO庫(kù)。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,確定SO庫(kù)加載失敗的原因?yàn)镾O文件不完整的方式包括:解析SO庫(kù)安裝包,將加載的當(dāng)前目錄下的SO文件的文件大小 與所述解析SO庫(kù)安裝包中解析出的SO文件的文件大小進(jìn)行比較,如果加載的SO文件的文件大小與安裝包中的SO文件的文件大小不一致,則確定SO庫(kù)加載失敗的原因是SO文件不完整。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,確定SO庫(kù)加載失敗的原因?yàn)镾O文件被篡改的方式包括:將加載的當(dāng)前目錄下的SO文件的更新時(shí)間與安裝SO庫(kù)安裝包的安裝時(shí)間進(jìn)行比較,如果更新時(shí)間和安裝時(shí)間不一致,則確定SO庫(kù)加載失敗的原因是SO文件被篡改。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,如果確定SO庫(kù)加載失敗的原因是找不到SO庫(kù)中SO文件的目錄,則選擇所述使用全路徑的方式或者使用文件加載的方式加載SO庫(kù)。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,所述使用全路徑的方式具體包括:通過(guò)調(diào)用定義了SO文件的全路徑名參數(shù)的System.load函數(shù)來(lái)尋找SO文件目錄。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,所述使用文件加載的具體方式包括:通過(guò)調(diào)用定義了SO文件的文件名參數(shù)的System.loadLibrary函數(shù)來(lái)尋找SO文件目錄。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,如果確定SO庫(kù)加載失敗的原因是多進(jìn)程加載SO庫(kù)導(dǎo)致的加載沖突,則選擇所述使用文件鎖的方式保證僅多個(gè)進(jìn)程之一加載SO庫(kù)。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,所述使用文件鎖的方式具體包括:當(dāng)多個(gè)進(jìn)程之一加載SO庫(kù)并對(duì)所述SO庫(kù)中的SO文件執(zhí)行寫操作時(shí),使用文件鎖對(duì)執(zhí)行寫操作的所述SO文件加鎖,當(dāng)所述寫操作結(jié)束后釋放文件鎖。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,在執(zhí)行所述選擇以下加載方式之一加載SO庫(kù)后,如果加載仍然失敗,則轉(zhuǎn)至執(zhí)行所述確定SO庫(kù)加載失敗的原因的操作。
一種SO庫(kù)加載的裝置,所述裝置包括:
確定單元,用于確定SO庫(kù)加載失敗的原因;
加載單元,用于依據(jù)SO庫(kù)加載失敗的原因選擇以下加載方式之一加載SO庫(kù):
釋放并重新安裝包含所述SO庫(kù)的安裝包;
使用全路徑的方式或者使用文件加載的方式加載SO庫(kù);
使用文件鎖的方式保證僅多個(gè)進(jìn)程之一加載SO庫(kù)。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,如果所述確定單元確定SO庫(kù)加載失敗的原因是所述SO庫(kù)中的SO文件不存在、SO文件不完整、或者SO文件被篡改,則所述加載單元選擇所述釋放并重新安裝包含所述SO庫(kù)的安裝包的方式加載SO庫(kù)。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,所述確定單元確定SO庫(kù)加載失敗的原因?yàn)镾O文件不完整的方式包括:解析SO庫(kù)安裝包,將加載的當(dāng)前目錄下的SO文件的文件大小與所述解析SO庫(kù)安裝包中解析出的SO文件的文件大小進(jìn)行比較,如果加載的SO文件的文件大小與安裝包中的SO文件的文件大小不一致,則確定SO庫(kù)加載失敗的原因是SO文件不完整。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,所述確定單元確定SO庫(kù)加載失敗的原因?yàn)镾O文件被篡改的方式包括:將加載的當(dāng)前目錄下的SO文件的更新時(shí)間與安裝SO庫(kù)安裝包的安裝時(shí)間進(jìn)行比較,如果更新時(shí)間和安裝時(shí)間不一致,則確定SO庫(kù)加載失敗的原因是SO文件被篡改。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,如果所述確定單元確定SO庫(kù)加載失敗的原因是找不到SO庫(kù)中SO文件的目錄,則加載單元選擇所述使用全路徑的方式或者使用文件加載的方式加載SO庫(kù)。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,所述使用全路徑的方式具體包括:通過(guò)調(diào)用定義了SO文件的全路徑名參數(shù)的System.load函數(shù)來(lái)尋找SO文件目錄。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,所述使用文件加載的具體方式包括:通過(guò)調(diào)用定義了SO文件的文件名參數(shù)的System.loadLibrary函數(shù)來(lái)尋找SO文件目錄。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,如果所述確定單元確定SO庫(kù)加載失敗的原因是多進(jìn)程加載SO庫(kù)導(dǎo)致的加載沖突,則所述加載單元選擇所述使用文件鎖的方式保證僅多個(gè)進(jìn)程之一加載SO庫(kù)。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,所述使用文件鎖的方式具體包括:當(dāng)多個(gè)進(jìn)程之一加載SO庫(kù)并對(duì)所述SO庫(kù)中的SO文件執(zhí)行寫操作時(shí),使用文件鎖對(duì)執(zhí)行寫操作的所述SO文件加鎖,當(dāng)所述寫操作結(jié)束后釋放文件鎖。
根據(jù)本發(fā)明一優(yōu)選實(shí)施例,在所述加載單元執(zhí)行所述選擇以下加載方式之一加載SO庫(kù)后,如果加載仍然失敗,則轉(zhuǎn)至由確定單元執(zhí)行所述確定SO庫(kù)加載失敗的原因的操作。
由以上技術(shù)方案可以看出,本發(fā)明提供的方法和裝置,基于SO庫(kù)自身的調(diào)用邏輯對(duì)可能導(dǎo)致SO庫(kù)加載失敗的難以捕捉的原因進(jìn)行排查,并依據(jù)SO庫(kù)加載失敗的原因選擇多個(gè)加載方式之一加載SO庫(kù),從而保證了SO庫(kù)盡量加載成功。
【附圖說(shuō)明】
圖1為本發(fā)明實(shí)施例一提供的一種SO庫(kù)加載方法的流程圖;
圖2為本發(fā)明實(shí)施例二提供的一種依次確定SO庫(kù)加載失敗的原因并選擇對(duì)應(yīng)的加載方式的SO庫(kù)加載方法流程圖;
圖3為本發(fā)明實(shí)施例三提供的一種SO庫(kù)加載裝置的結(jié)構(gòu)示意圖;
圖4為本發(fā)明實(shí)施例四提供的一種依次確定SO庫(kù)加載失敗的原因并選擇對(duì)應(yīng)的加載方式的SO庫(kù)加載裝置的結(jié)構(gòu)示意圖。
【具體實(shí)施方式】
為了使本發(fā)明的目的、技術(shù)方案和優(yōu)點(diǎn)更加清楚,下面結(jié)合附圖和具體實(shí)施例對(duì)本發(fā)明進(jìn)行詳細(xì)描述。
實(shí)施例一、
參照?qǐng)D1,圖1示出了根據(jù)本發(fā)明實(shí)施例一的一種SO庫(kù)加載的方法的流程圖,具體流程為:
101、確定SO庫(kù)加載失敗的原因。
當(dāng)應(yīng)用加載SO庫(kù)失敗時(shí),可能會(huì)提示沒(méi)有文件或目錄,例如會(huì)顯示這 樣的提示信息“error while loading shared libraries:libtcmal loc_mininal.SO.4No such file or directory”。
當(dāng)SO庫(kù)中的SO文件不存在、不完整或者被篡改等,該SO文件自身存在的一系列問(wèn)題可能造成SO庫(kù)加載失敗,因此可以先確定SO庫(kù)加載失敗是否是由SO文件不存在、不完整或者被篡改等其自身原因?qū)е碌摹?/p>
其中導(dǎo)致SO文件不存在的原因又有很多,例如由于在Android中調(diào)用SO文件時(shí),往往都要將對(duì)應(yīng)的SO文件打包進(jìn)安裝包(apk)。因此提示SO文件不存在的這種情況通常是因?yàn)樗枰腶pk包沒(méi)有安裝;除此之外,SO文件拷入不成功、該文件已被第三方應(yīng)用刪除、文件丟失等,也可能使SO文件不存在,在此不再一一列舉。
本發(fā)明所指的apk是AndroidPacKage的縮寫,即Android安裝包(apk)。apk是類似Symbian Sis或Sisx的文件格式。通過(guò)將apk文件直接傳到Android模擬器或Android手機(jī)中執(zhí)行即可安裝。apk文件其實(shí)是zip格式,但后綴名被修改為apk。Android系統(tǒng)在運(yùn)行一個(gè)程序時(shí)首先需要將apk通過(guò)UnZip解壓,然后直接執(zhí)行安裝。
而應(yīng)用找不到SO庫(kù)中SO文件的相應(yīng)目錄、多進(jìn)程加載沖突也是導(dǎo)致SO庫(kù)加載失敗的原因。
因此步驟101中需要首先確定SO庫(kù)加載失敗的原因是1011、SO文件不存在,1012、SO文件不完整或被篡改,1013、找不到SO庫(kù)中SO文件的目錄,或者1014、多進(jìn)程加載SO庫(kù)導(dǎo)致的加載沖突等等多個(gè)原因中的哪一種,從而依據(jù)SO庫(kù)加載失敗的原因選擇相應(yīng)的記載方式來(lái)加載SO庫(kù)。
102、依據(jù)SO庫(kù)加載失敗的原因選擇以下加載方式之一加載SO庫(kù):1021、釋放并重新安裝包含所述SO庫(kù)的安裝包,1022、通過(guò)使用全路徑的方式加載SO庫(kù),1023、使用文件加載的方式加載SO庫(kù),或者1024、使用文件鎖的方式保證僅多個(gè)進(jìn)程之一加載SO庫(kù)。
具體地,可以通過(guò)校驗(yàn)來(lái)確定SO庫(kù)加載失敗的原因101是否是SO庫(kù)中的SO文件不存在1011,SO文件不完整或者被篡改1012,如果確定是上述原 因之一,可以通過(guò)釋放并重新安裝apk包的方式1021加載SO庫(kù)。
另外,在執(zhí)行了一次釋放并重新安裝apk包加載SO庫(kù)后,可以再次嘗試一次校驗(yàn)來(lái)確定是否存在SO文件不存在、不完整、或者被篡改的原因,從而最大限度的排除由SO文件自身原因?qū)е碌募虞d失敗。
當(dāng)然,也可以再次嘗試一次以上的校驗(yàn),其嘗試的任何次數(shù)均在本發(fā)明的保護(hù)范圍內(nèi)。
如果在SO文件的相應(yīng)目錄下并沒(méi)有相應(yīng)的SO文件,則確定文件不存在。
如果通過(guò)解析SO庫(kù)安裝包,將加載的當(dāng)前目錄下的SO文件的文件大小與解析SO庫(kù)安裝包中解析出的SO文件的文件大小進(jìn)行比較,發(fā)現(xiàn)加載的SO文件的文件大小與安裝包中的SO文件的文件大小不一致,則可以確定SO庫(kù)加載失敗的原因是SO文件不完整。
如果將加載的當(dāng)前目錄下的SO文件的更新時(shí)間與安裝SO庫(kù)安裝包的安裝時(shí)間進(jìn)行比較,發(fā)現(xiàn)更新時(shí)間和安裝時(shí)間不一致,則可以確定SO庫(kù)加載失敗的原因是SO文件被篡改。
以上對(duì)確定SO文件是否不存在、不完整或是否被篡改僅舉出了一種示例,但并不限于上述示例,其他確定SO文件是否不存在、不完整或被篡改的具體方式均包含在本發(fā)明所保護(hù)的范圍內(nèi)。
如果確定SO庫(kù)加載失敗的原因是找不到SO庫(kù)中SO文件的目錄,則選擇所述使用全路徑的方式或者使用文件加載的方式加載SO庫(kù)。
其中,可以通過(guò)調(diào)用定義了SO文件的全路徑名參數(shù)的System.load函數(shù)來(lái)使用全路徑方式尋找SO文件目錄。也可以通過(guò)調(diào)用定義了SO文件的文件名參數(shù)的System.loadLibrary函數(shù)來(lái)使用文件加載的方式尋找SO文件目錄。
在通過(guò)全路徑方式尋找SO文件目錄失敗后,還可以進(jìn)一步通過(guò)釋放并重新安裝apk包的方式再次加載SO庫(kù)。
如果確定SO庫(kù)加載失敗的原因是多進(jìn)程加載SO庫(kù)導(dǎo)致的加載沖突,可以在多個(gè)進(jìn)程之一加載SO庫(kù)并對(duì)SO庫(kù)中的SO文件執(zhí)行寫操作時(shí),使用文件 鎖對(duì)執(zhí)行寫操作的SO文件加鎖,當(dāng)寫操作結(jié)束后釋放文件鎖,從而使用文件鎖的方式保證僅多個(gè)進(jìn)程之一加載SO庫(kù)。
在執(zhí)行所述選擇以下加載方式之一加載SO庫(kù)后,如果加載仍然失敗,則轉(zhuǎn)至執(zhí)行101的步驟,重新確定SO庫(kù)加載失敗的原因并有針對(duì)性的執(zhí)行相應(yīng)操作。
本實(shí)施例中可以依據(jù)SO庫(kù)加載失敗的原因而選擇不同的SO庫(kù)加載方式來(lái)加載SO庫(kù),多個(gè)SO庫(kù)加載方式中,其執(zhí)行不分先后順序,一切能夠保證SO庫(kù)成功加載的執(zhí)行順序的組合方式均在本發(fā)明的保護(hù)范圍內(nèi)。
雖然多個(gè)SO庫(kù)加載方式的執(zhí)行不分先后順序,只要能通過(guò)各流程而成功加載SO庫(kù)文件,則均在本發(fā)明的保護(hù)范圍內(nèi)。但為了便于理解,以下選取了一種執(zhí)行順序的組合,并從依次確定SO庫(kù)加載失敗的原因并選擇對(duì)應(yīng)的加載方式加載SO庫(kù)的角度,對(duì)實(shí)施例一描述的SO庫(kù)加載方法進(jìn)行了進(jìn)一步說(shuō)明。
實(shí)施例二、
參照?qǐng)D2,圖2示出了根據(jù)本發(fā)明實(shí)施例二的一種依次確定SO庫(kù)加載失敗的原因并選擇對(duì)應(yīng)的加載方式的SO庫(kù)加載方法流程圖,具體流程為:
201、校驗(yàn)SO文件是否存在,以排除SO文件不存在而導(dǎo)致的SO庫(kù)加載失敗。
在步驟201中,如果應(yīng)用加載SO庫(kù)失敗,可以通過(guò)校驗(yàn)的方式確定SO文件是否存在。如果發(fā)現(xiàn)SO文件不存在時(shí),可以通過(guò)釋放apk包并重新安裝的方式來(lái)解決,并且在重新安裝apk包后,再次嘗試一次SO文件是否存在的校驗(yàn),以保證SO文件的真實(shí)存在。
如果通過(guò)步驟201發(fā)現(xiàn)系統(tǒng)要加載的SO庫(kù)中SO文件已經(jīng)存在于相應(yīng)的目錄下面,但仍然提示無(wú)法加載SO庫(kù),則有可能是SO文件由于不完整或被篡改而導(dǎo)致其加載失敗,因此可以通過(guò)流程202對(duì)SO文件進(jìn)行進(jìn)一步校驗(yàn)。
202、校驗(yàn)SO文件是否完整或是否被篡改。
當(dāng)SO文件已經(jīng)存在,但加載SO庫(kù)仍然失敗時(shí),其加載失敗有可能是由 已經(jīng)存在的SO文件不完整、被篡改等原因?qū)е碌摹6鳶O文件缺少字節(jié)、被損壞、被修改均可以引起SO文件不完整或被篡改。
第一種:校驗(yàn)SO文件的大小。
校驗(yàn)SO文件大小的方式可以為,解析apk包,將當(dāng)前位于SO文件目錄下的SO文件與所解析的apk包中的相應(yīng)文件進(jìn)行比較,以確定加載的SO文件的大小與apk包中的文件大小是否一致。如果一致,說(shuō)明文件是完整的,則繼續(xù)校驗(yàn)SO文件是否給篡改;反之,則校驗(yàn)失敗,由此表明SO文件不完整。
在通過(guò)校驗(yàn)發(fā)現(xiàn)SO文件不完整時(shí),可以通過(guò)釋放apk包并重新安裝的方式來(lái)解決,并且在重新安裝apk包后,再次嘗試一次SO完整性的校驗(yàn),以保證SO文件的準(zhǔn)確性。
第二種,校驗(yàn)SO文件的更新時(shí)間。
如果加載的SO文件相比于安裝apk的安裝時(shí)間,該SO文件的更新時(shí)間發(fā)生改變,則有可能SO文件遭到過(guò)篡改或破壞,從而導(dǎo)致加載失敗。
優(yōu)選地,可以通過(guò)檢查時(shí)間戳的方式來(lái)校驗(yàn)SO文件的更新時(shí)間,具體地:
當(dāng)安裝apk包時(shí),基于安裝apk的時(shí)間設(shè)置時(shí)間戳,優(yōu)選地,可以基于首次安裝的apk包設(shè)置時(shí)間戳,將當(dāng)前目錄下的SO文件更新時(shí)間與時(shí)間戳進(jìn)行比較,如果一致,說(shuō)明文件是原始文件,沒(méi)有被篡改,該原因排查后,可以進(jìn)行全路徑方式加載;反之,SO文件在安裝apk包以后的時(shí)間被進(jìn)行過(guò)修改,則校驗(yàn)失敗,由此表明SO文件被篡改。
在校驗(yàn)SO文件發(fā)現(xiàn)其被篡改時(shí),可以通過(guò)釋放apk包并重新安裝的方式來(lái)解決,并且在重新安裝apk包后,再次嘗試一次SO是否被篡改的校驗(yàn),以保證SO文件的準(zhǔn)確性。
如果通過(guò)201發(fā)現(xiàn)系統(tǒng)要加載的SO文件已經(jīng)存在,通過(guò)202校驗(yàn)確定SO文件完整且沒(méi)有被篡改,即校驗(yàn)成功,但SO庫(kù)仍然加載失敗時(shí),則還有可能是系統(tǒng)沒(méi)有找到已有SO文件的加載目錄而導(dǎo)致其加載失敗,因此可以進(jìn) 入203,通過(guò)全路徑加載SO文件的方式尋找目錄。
如果在201和202中經(jīng)過(guò)有限次的校驗(yàn)發(fā)現(xiàn)SO文件仍然不存在、不完整或被篡改,則校驗(yàn)失敗,不再繼續(xù)嘗試SO庫(kù)加載。
203、通過(guò)全路徑的方式加載SO庫(kù)。
全路徑是指從根目錄開始的路徑,使用全路徑可以唯一定位一個(gè)文件或者文件夾。
本實(shí)施例可以使用System.load函數(shù)加載SO文件,此函數(shù)的參數(shù)為SO文件全路徑名。
例如System.load("/usr/lib/TestJNI.SO"),其中l(wèi)ibTestJNI.SO是java.library.path所指向的路徑。
當(dāng)系統(tǒng)本身發(fā)生讀取失敗、解碼操作失敗等錯(cuò)誤時(shí),可以導(dǎo)致通過(guò)路徑加載SO庫(kù)失敗,上述失敗的概率雖然相比于SO文件不存在、不完整或被篡改的概率小,但若存在問(wèn)題則會(huì)產(chǎn)生較大的影響。因此如果全路徑加載失敗時(shí),可以通過(guò)釋放apk包并重新安裝的方式來(lái)解決,并且在重新安裝apk包后,再次嘗試一次全路徑加載SO文件,以確保加載成功。
本實(shí)施例中僅以再次嘗試一次校驗(yàn)或者再次嘗試一次全路徑加載進(jìn)行了描述,然而并不限于此,其他有限次數(shù)的嘗試加載均在本發(fā)明保護(hù)的范圍內(nèi)。
由于系統(tǒng)中通過(guò)全路徑加載的方式是在固定的幾個(gè)路徑下去查找,加載的是路徑而不是文件,該方式排除了其路徑之外的所有查找SO文件的手段,因此在通過(guò)釋放并重新安裝apk包,或者再次嘗試全路徑加載仍然失敗時(shí),可以通過(guò)204來(lái)嘗試使用除全路徑外的其他查找手段來(lái)加載SO文件。
204、通過(guò)加載文件的方式加載SO庫(kù)。
本實(shí)施例可以通過(guò)使用System.loadLibrary函數(shù)來(lái)加載SO庫(kù),System.loadLibrary的功能是查找并加載某個(gè)庫(kù)文件,其參數(shù)為庫(kù)文件名,使用此方法可加載系統(tǒng)目錄中的SO文件。
例如
System.loadLibrary("data/data/xxx.xxx.xxx/lib/xx.SO")或者
System.loadLibrary("xx")。
通過(guò)加載文件的方式,可以在通過(guò)全路徑加載SO庫(kù)失敗時(shí),以另一種方式再次嘗試查找SO文件從而實(shí)現(xiàn)SO庫(kù)的加載,以此確保加載成功。
當(dāng)嘗試完所有查找手段加載SO庫(kù)時(shí),仍然可能出現(xiàn)SO庫(kù)加載失敗的問(wèn)題,而多進(jìn)程加載SO庫(kù)所引起的沖突,也會(huì)成為導(dǎo)致加載失敗的原因,因此可以通過(guò)205來(lái)解決多進(jìn)程加載失敗的問(wèn)題。
205、如果是多個(gè)進(jìn)程加載SO庫(kù),則使用文件鎖。
具體地,若多個(gè)進(jìn)程加載SO庫(kù),例如一個(gè)進(jìn)程未釋放SO庫(kù)而另一個(gè)進(jìn)程在寫過(guò)程,上述操作同樣會(huì)引起SO庫(kù)的加載錯(cuò)誤,因此當(dāng)多個(gè)進(jìn)程加載SO庫(kù)時(shí),可以使用文件鎖(filelock)在寫操作時(shí)對(duì)其中一個(gè)可寫文件(w)加鎖(trylock),保證同時(shí)只有一個(gè)進(jìn)程可以拿到文件鎖,這個(gè)進(jìn)程從而可以對(duì)文件做訪問(wèn),直到該進(jìn)程的操作完成時(shí)再通過(guò)FileLock.release()語(yǔ)句釋放文件鎖。
通過(guò)文件鎖可以控制不同程序?qū)ν晃募牟l(fā)訪問(wèn),這樣的機(jī)制保證了某進(jìn)程獲得文件鎖后,操作系統(tǒng)將保證其它進(jìn)程無(wú)法對(duì)文件做操作,這樣,進(jìn)程就可以通過(guò)FileLock來(lái)實(shí)現(xiàn)進(jìn)程間的互斥運(yùn)行。從而避免由于多個(gè)進(jìn)程同時(shí)對(duì)SO庫(kù)的操作而引起SO庫(kù)加載失敗。
實(shí)施例三、
參照?qǐng)D3,圖3示出了根據(jù)本發(fā)明實(shí)施例三的一種SO庫(kù)加載裝置的結(jié)構(gòu)示意圖,該SO庫(kù)加載裝置可以包括:確定單元301和加載單元302,以下對(duì)各個(gè)單元的構(gòu)成和功能進(jìn)行詳細(xì)描述:
確定單元301,用于確定SO庫(kù)加載失敗的原因。
當(dāng)SO庫(kù)中的SO文件不存在、不完整或者被篡改等,該SO文件自身存在的一系列問(wèn)題可能造成SO庫(kù)加載失敗,因此可以先確定SO庫(kù)加載失敗是否是由SO文件不存在、不完整或者被篡改等其自身原因?qū)е碌摹?/p>
其中導(dǎo)致SO文件不存在的原因又有很多,例如由于在Android中調(diào)用 SO文件時(shí),往往都要將對(duì)應(yīng)的SO文件打包進(jìn)安裝包(apk)。因此提示SO文件不存在的這種情況通常是因?yàn)樗枰腶pk包沒(méi)有安裝;除此之外,SO文件拷入不成功、該文件已被第三方應(yīng)用刪除、文件丟失等,也可能使SO文件不存在,在此不再一一列舉。
而應(yīng)用找不到SO庫(kù)中SO文件的相應(yīng)目錄、多進(jìn)程加載沖突也是導(dǎo)致SO庫(kù)加載失敗的原因。
因此需要首先通過(guò)確定單元301確定SO庫(kù)加載失敗的原因是SO文件不存在,SO文件不完整或被篡改,找不到SO庫(kù)中SO文件的目錄,或者多進(jìn)程加載SO庫(kù)導(dǎo)致的加載沖突等等多個(gè)原因中的哪一種,從而依據(jù)SO庫(kù)加載失敗的原因選擇相應(yīng)的記載方式來(lái)加載SO庫(kù)。
加載單元302,用于依據(jù)SO庫(kù)加載失敗的原因選擇以下加載方式之一加載SO庫(kù):釋放并重新安裝包含所述SO庫(kù)的安裝包,通過(guò)使用全路徑的方式加載SO庫(kù),使用文件加載的方式加載SO庫(kù),或者使用文件鎖的方式保證僅多個(gè)進(jìn)程之一加載SO庫(kù)。
具體地,確定單元可以通過(guò)校驗(yàn)來(lái)確定SO庫(kù)加載失敗的原因是否是SO庫(kù)中的SO文件不存在,SO文件不完整或者被篡改,如果確定是上述原因之一,則可以使加載單元執(zhí)行釋放并重新安裝apk包的操作加載SO庫(kù)。
另外,在執(zhí)行了一次釋放并重新安裝apk包加載SO庫(kù)后,可以再次嘗試一次校驗(yàn)來(lái)確定是否存在SO文件不存在、不完整、或者被篡改的原因,從而最大限度的排除由SO文件自身原因?qū)е碌募虞d失敗。
當(dāng)然,也可以再次嘗試一次以上的校驗(yàn),其嘗試的任何次數(shù)均在本發(fā)明的保護(hù)范圍內(nèi)。
如果確定單元在SO文件的相應(yīng)目錄下并沒(méi)有相應(yīng)的SO文件,則確定文件不存在。
如果確定單元通過(guò)解析SO庫(kù)安裝包,將加載的當(dāng)前目錄下的SO文件的文件大小與解析SO庫(kù)安裝包中解析出的SO文件的文件大小進(jìn)行比較,發(fā)現(xiàn)加載的SO文件的文件大小與安裝包中的SO文件的文件大小不一致,則可以 確定SO庫(kù)加載失敗的原因是SO文件不完整。
如果確定單元將加載的當(dāng)前目錄下的SO文件的更新時(shí)間與安裝SO庫(kù)安裝包的安裝時(shí)間進(jìn)行比較,發(fā)現(xiàn)更新時(shí)間和安裝時(shí)間不一致,則可以確定SO庫(kù)加載失敗的原因是SO文件被篡改。
以上對(duì)確定SO文件是否不存在、不完整或是否被篡改僅舉出了一種示例,但并不限于上述示例,其他確定SO文件是否不存在、不完整或被篡改的具體方式均包含在本發(fā)明所保護(hù)的范圍內(nèi)。
如果確定SO庫(kù)加載失敗的原因是找不到SO庫(kù)中SO文件的目錄,則加載單元選擇使用全路徑的方式或者使用文件加載的方式加載SO庫(kù)。
其中,加載單元302可以通過(guò)調(diào)用定義了SO文件的全路徑名參數(shù)的System.load函數(shù)來(lái)使用全路徑方式尋找SO文件目錄。也可以通過(guò)調(diào)用定義了SO文件的文件名參數(shù)的System.loadLibrary函數(shù)來(lái)使用文件加載的方式尋找SO文件目錄。
在通過(guò)全路徑方式尋找SO文件目錄失敗后,還可以進(jìn)一步通過(guò)釋放并重新安裝apk包的方式再次加載SO庫(kù)。
如果確定SO庫(kù)加載失敗的原因是多進(jìn)程加載SO庫(kù)導(dǎo)致的加載沖突,加載單元可以在多個(gè)進(jìn)程之一加載SO庫(kù)并對(duì)SO庫(kù)中的SO文件執(zhí)行寫操作時(shí),使用文件鎖對(duì)執(zhí)行寫操作的SO文件加鎖,當(dāng)寫操作結(jié)束后釋放文件鎖,從而使用文件鎖的方式保證僅多個(gè)進(jìn)程之一加載SO庫(kù)。
在執(zhí)行所述選擇以下加載方式之一加載SO庫(kù)后,如果加載仍然失敗,則轉(zhuǎn)至由確定單元301重新確定SO庫(kù)加載失敗的原因并有針對(duì)性的執(zhí)行相應(yīng)操作。
本實(shí)施例中可以依據(jù)SO庫(kù)加載失敗的原因而選擇不同的SO庫(kù)加載方式來(lái)加載SO庫(kù),多個(gè)SO庫(kù)加載方式中,其執(zhí)行不分先后順序,一切能夠保證SO庫(kù)成功加載的執(zhí)行順序的組合方式均在本發(fā)明的保護(hù)范圍內(nèi)。
雖然加載單元加載SO庫(kù)的順序不分先后,只要其能夠成功加載SO庫(kù)文件就均在本發(fā)明的保護(hù)范圍內(nèi),但為了便于理解,以下選取了一種加載單元 加載SO庫(kù)的執(zhí)行順序的組合,并從依次確定SO庫(kù)加載失敗的原因并選擇對(duì)應(yīng)的加載方式加載SO庫(kù)的角度,對(duì)實(shí)施例三描述的SO庫(kù)加載裝置進(jìn)行了進(jìn)一步說(shuō)明。
實(shí)施例四、
參照?qǐng)D4,圖4示出了根據(jù)本發(fā)明實(shí)施例三的一種依次確定SO庫(kù)加載失敗的原因并選擇對(duì)應(yīng)的加載方式的SO庫(kù)加載裝置的結(jié)構(gòu)示意圖,該裝置具體包括:
校驗(yàn)單元401,用于校驗(yàn)SO文件是否存在、是否完整或是否被篡改,以排除SO文件不存在而導(dǎo)致的SO庫(kù)加載失敗。
具體地,如果應(yīng)用加載SO庫(kù)失敗,可以通過(guò)校驗(yàn)單元401來(lái)確定SO文件是否存在。如果發(fā)現(xiàn)SO文件不存在時(shí),可以通過(guò)第一安裝單元4012執(zhí)行釋放apk包并重新安裝的操作來(lái)解決SO文件不存在的問(wèn)題,并且在重新安裝apk包后,再次嘗試一次SO文件是否存在的校驗(yàn),以保證SO文件的真實(shí)存在。
如果經(jīng)校驗(yàn)發(fā)現(xiàn)系統(tǒng)要加載的SO庫(kù)中SO文件已經(jīng)存在于相應(yīng)的目錄下面,但仍然提示無(wú)法加載SO庫(kù),則有可能是SO文件由于不完整或被篡改而導(dǎo)致其加載失敗,因此可以通過(guò)校驗(yàn)裝置401繼續(xù)對(duì)SO文件進(jìn)行不完整或被篡改的校驗(yàn)。
其中,SO文件缺少字節(jié)、被損壞、被修改均可以引起SO文件不完整或被篡改。
校驗(yàn)單元401可以通過(guò)以下方式對(duì)SO文件是否不完整或是否被篡改進(jìn)行校驗(yàn)
第一種:校驗(yàn)SO文件的大小。
校驗(yàn)SO文件大小的方式可以為,解析apk包,將當(dāng)前位于SO文件目錄下的SO文件與所解析的apk包中的相應(yīng)文件進(jìn)行比較,以確定加載的SO文件的大小與apk包中的文件大小是否一致。如果一致,說(shuō)明文件是完整的,則繼續(xù)校驗(yàn)SO文件是否給篡改;反之,則校驗(yàn)失敗,由此表明SO文件不完 整。
在通過(guò)校驗(yàn)發(fā)現(xiàn)SO文件不完整時(shí),可以通過(guò)釋放apk包并重新安裝的方式來(lái)解決,并且在重新安裝apk包后,再次嘗試一次SO完整性的校驗(yàn),以保證SO文件的準(zhǔn)確性。
第二種,校驗(yàn)SO文件的更新時(shí)間。
如果加載的SO文件相比于安裝apk的安裝時(shí)間,該SO文件的更新時(shí)間發(fā)生改變,則有可能SO文件遭到過(guò)篡改或破壞,從而導(dǎo)致加載失敗。
優(yōu)選地,可以通過(guò)檢查時(shí)間戳的方式來(lái)校驗(yàn)SO文件的更新時(shí)間,具體地:
當(dāng)安裝apk包時(shí),基于安裝apk的時(shí)間設(shè)置時(shí)間戳,優(yōu)選地,可以基于首次安裝的apk包設(shè)置時(shí)間戳,將當(dāng)前目錄下的SO文件更新時(shí)間與時(shí)間戳進(jìn)行比較,如果一致,說(shuō)明文件是原始文件,沒(méi)有被篡改,該原因排查后,可以進(jìn)行全路徑方式加載;反之,SO文件在安裝apk包以后的時(shí)間被進(jìn)行過(guò)修改,則校驗(yàn)失敗,由此表明SO文件被篡改。
在校驗(yàn)SO文件發(fā)現(xiàn)其被篡改的問(wèn)題時(shí),可以通過(guò)第二安裝單元4022執(zhí)行釋放apk包并重新安裝的操作來(lái)解決,并且在重新安裝apk包后,再次嘗試一次SO文件是否被篡改的校驗(yàn),以保證SO文件的準(zhǔn)確性。
如果通過(guò)校驗(yàn)裝置401的校驗(yàn)發(fā)現(xiàn)系統(tǒng)要加載的SO文件已經(jīng)存在,且其完整和沒(méi)有被篡改,即校驗(yàn)成功,但SO庫(kù)仍然加載失敗時(shí),則還有可能是系統(tǒng)沒(méi)有找到已有SO文件的加載目錄而導(dǎo)致其加載失敗,因此可以通過(guò)全路徑加載單元402執(zhí)行全路徑加載SO文件,以尋找SO文件的目錄。
如果校驗(yàn)單元401經(jīng)過(guò)有限次的校驗(yàn)發(fā)現(xiàn)SO文件仍然不存在、不完整或被篡改,則校驗(yàn)失敗,不再繼續(xù)嘗試SO庫(kù)加載。
全路徑加載單元402,用于通過(guò)全路徑的方式加載SO庫(kù)。
全路徑是指從根目錄開始的路徑,使用全路徑可以唯一定位一個(gè)文件或者文件夾。
本實(shí)施例可以使用System.load函數(shù)加載SO文件,此函數(shù)的參數(shù)為SO 文件全路徑名。
當(dāng)系統(tǒng)本身發(fā)生讀取失敗、解碼操作失敗等錯(cuò)誤時(shí),可以導(dǎo)致通過(guò)路徑加載SO庫(kù)失敗,上述失敗的概率雖然相比于SO文件不存在、不完整或被篡改的概率小,但若存在問(wèn)題則會(huì)產(chǎn)生較大的影響。因此如果全路徑加載失敗時(shí),可以通過(guò)釋放apk包并重新安裝的方式來(lái)解決,并且在重新安裝apk包后,再次嘗試一次全路徑加載SO文件,以確保加載成功。
本實(shí)施例中僅以再次嘗試一次校驗(yàn)或者再次嘗試一次全路徑加載進(jìn)行了描述,然而并不限于此,其他有限次數(shù)的嘗試加載均在本發(fā)明保護(hù)的范圍內(nèi)。
由于系統(tǒng)中通過(guò)全路徑加載的方式是在固定的幾個(gè)路徑下去查找,加載的是路徑而不是文件,該方式排除了其路徑之外的所有查找SO文件的手段,因此在通過(guò)釋放并重新安裝apk包,或者再次嘗試全路徑加載仍然失敗時(shí),可以通過(guò)加載文件單元403來(lái)嘗試使用除全路徑外的其他查找手段來(lái)加載SO文件。
加載文件單元403,用于通過(guò)加載文件的方式加載SO庫(kù)。
本實(shí)施例可以通過(guò)使用System.loadLibrary函數(shù)來(lái)加載SO庫(kù),System.loadLibrary的功能是查找并加載某個(gè)庫(kù)文件,其參數(shù)為庫(kù)文件名,使用此方法可加載系統(tǒng)目錄中的SO文件。
通過(guò)加載文件的方式,可以在通過(guò)全路徑加載SO庫(kù)失敗時(shí),以另一種方式再次嘗試查找SO文件從而實(shí)現(xiàn)SO庫(kù)的加載,以此確保加載成功。
當(dāng)嘗試完所有查找手段加載SO庫(kù)時(shí),仍然可能出現(xiàn)SO庫(kù)加載失敗的問(wèn)題,而多進(jìn)程加載SO庫(kù)所引起的沖突,也會(huì)成為導(dǎo)致加載失敗的原因,因此可以通過(guò)多進(jìn)程加載單元404來(lái)解決多進(jìn)程加載失敗的問(wèn)題。
多進(jìn)程加載單元404,用于當(dāng)多個(gè)進(jìn)程加載SO庫(kù)時(shí),使用文件鎖鎖定進(jìn)程。
具體地,若多個(gè)進(jìn)程加載SO庫(kù),例如一個(gè)進(jìn)程未釋放SO庫(kù)而另一個(gè)進(jìn)程在寫過(guò)程,上述操作同樣會(huì)引起SO庫(kù)的加載錯(cuò)誤,因此當(dāng)多個(gè)進(jìn)程加載 SO庫(kù)時(shí),可以使用文件鎖(filelock)在寫操作時(shí)對(duì)其中一個(gè)可寫文件(w)加鎖(trylock),保證同時(shí)只有一個(gè)進(jìn)程可以拿到文件鎖,這個(gè)進(jìn)程從而可以對(duì)文件做訪問(wèn),直到該進(jìn)程的操作完成時(shí)再通過(guò)FileLock.release()語(yǔ)句釋放文件鎖。
通過(guò)文件鎖可以控制不同程序?qū)ν晃募牟l(fā)訪問(wèn),這樣的機(jī)制保證了某進(jìn)程獲得文件鎖后,操作系統(tǒng)將保證其它進(jìn)程無(wú)法對(duì)文件做操作,這樣,進(jìn)程就可以通過(guò)FileLock來(lái)實(shí)現(xiàn)進(jìn)程間的互斥運(yùn)行。從而避免由于多個(gè)進(jìn)程同時(shí)對(duì)SO庫(kù)的操作而引起SO庫(kù)加載失敗。
基于本發(fā)明實(shí)施例所提供的SO庫(kù)加載的方法和裝置,當(dāng)在SO庫(kù)加載中遇到加載失敗的問(wèn)題時(shí),提出了一種解決加載失敗的具體解決方案,即從SO庫(kù)加載中可能導(dǎo)致加載失敗的可能原因入手,基于不同的原因給出相對(duì)應(yīng)的解決手段,通過(guò)在當(dāng)前目錄下釋放、安裝apk包的形式重新加載SO庫(kù),或者采用其他加載方式嘗試加載SO庫(kù),從而保證加載SO庫(kù)的成功率。
結(jié)合實(shí)施例三和實(shí)施例四不難看出,確定單元301中可以包含校驗(yàn)單元401,而加載單元302中可以包含第一安裝單元4012、第二安裝單元4022、全路徑加載單元402、加載文件單元403,或多進(jìn)程加載單元404。
在本發(fā)明所提供的幾個(gè)實(shí)施例中,應(yīng)該理解到,所揭露的系統(tǒng),裝置和方法,可以通過(guò)其它的方式實(shí)現(xiàn)。例如,以上所描述的裝置實(shí)施例僅僅是示意性的,例如,所述單元的劃分,僅僅為一種邏輯功能劃分,實(shí)際實(shí)現(xiàn)時(shí)可以有另外的劃分方式。
所述作為分離部件說(shuō)明的單元可以是或者也可以不是物理上分開的,作為單元顯示的部件可以是或者也可以不是物理單元,即可以位于一個(gè)地方,或者也可以分布到多個(gè)網(wǎng)絡(luò)單元上??梢愿鶕?jù)實(shí)際的需要選擇其中的部分或者全部單元來(lái)實(shí)現(xiàn)本實(shí)施例方案的目的。
另外,在本發(fā)明各個(gè)實(shí)施例中的各功能單元可以集成在一個(gè)處理單元中,也可以是各個(gè)單元單獨(dú)物理存在,也可以兩個(gè)或兩個(gè)以上單元集成在一個(gè)單元中。上述集成的單元既可以采用硬件的形式實(shí)現(xiàn),也可以采用硬件加 軟件功能單元的形式實(shí)現(xiàn)。
以上所述僅為本發(fā)明的較佳實(shí)施例而已,并不用以限制本發(fā)明,凡在本發(fā)明的精神和原則之內(nèi),所做的任何修改、等同替換、改進(jìn)等,均應(yīng)包含在本發(fā)明保護(hù)的范圍之內(nèi)。