1.動(dòng)態(tài)加載jar的作用及意義
a.反破解瑟押,關(guān)于加密等比較隱蔽及隱私的的代碼放在遠(yuǎn)端加載彪薛,即使別人破解了你的apk文件寂呛,也無法獲取這些關(guān)鍵的代碼缤灵,可以隨時(shí)更換安全策略伦籍,提高應(yīng)用的安全性;
b.間接解決方法數(shù)超過65535的限制腮出,不再將jar打入apk文件中
c.可以進(jìn)一步研究鸽斟,拓展成apk的動(dòng)態(tài)加載
2.原理
? ? Dalvik虛擬機(jī)如同其他Java虛擬機(jī)一樣,在運(yùn)行程序時(shí)首先需要將對應(yīng)的類加載到內(nèi)存中利诺。而在Java標(biāo)準(zhǔn)的虛擬機(jī)中,類加載可以從class文件中讀取剩燥,也可以是其他形式的二進(jìn)制流慢逾,因此,我們常常利用這一點(diǎn)灭红,在程序運(yùn)行時(shí)手動(dòng)加載Class侣滩,從而達(dá)到代碼動(dòng)態(tài)加載執(zhí)行的目的,然而Dalvik虛擬機(jī)畢竟不算是標(biāo)準(zhǔn)的Java虛擬機(jī)变擒,因此在類加載機(jī)制上君珠,它們有相同的地方,也有不同之處娇斑。我們必須區(qū)別對待策添,Dalvik虛擬機(jī)識別的是dex文件,而不是class文件毫缆。因此唯竹,我們供類加載的文件也只能是dex文件,或者包含有dex文件的.apk或.jar文件苦丁。
? ? ?Android中和類加載相關(guān)的兩個(gè)類:DexClassLoader和PathClassLoader
? DexClassLoader :可以加載jar/apk/dex浸颓,也可以從SD卡中加載,通過其靜態(tài)方法loadDex(path, outpath, 0) 得到DexFile對象;
? PathClassLoader: 只能加載已經(jīng)安裝到Android系統(tǒng)中的apk文件产上,通過構(gòu)造函數(shù)new DexFile(path)來產(chǎn)生DexFile對象棵磷。?
? 這兩者的區(qū)別在于DexClassLoader需要提供一個(gè)可寫的outpath路徑,用來釋放.apk包或者.jar包中的dex文件晋涣。也就是說PathClassLoader不能主動(dòng)從zip包中釋放出dex仪媒,因此只支持直接操作dex格式文件,或者已經(jīng)安裝的apk(因?yàn)橐呀?jīng)安裝的apk在cache中存在緩存的dex文件)姻僧, 而DexClassLoader可以支持.apk规丽、.jar和.dex文件,并且會(huì)在指定的outpath路徑釋放出dex文件撇贺。
? ?加載好類后赌莺,通常我們可以通過Java反射機(jī)制來使用這個(gè)類但是這樣效率相對不高,而且也比較復(fù)雜凌亂松嘶。更好的做法是定義一個(gè)interface艘狭,并將這個(gè)interface寫進(jìn)容器端。待加載的類翠订,繼承自這個(gè)interface巢音,并且有一個(gè)參數(shù)為空的構(gòu)造函數(shù),以使我們能夠通過Class的newInstance方法產(chǎn)生對象然后將對象強(qiáng)制轉(zhuǎn)換為interface對象尽超,就可以直接調(diào)用成員方法了官撼。
? 當(dāng)你的jar中包含或者使用了第三方的類庫你也可以定個(gè)規(guī)范的interface,并在你要加載的jar中實(shí)現(xiàn)這個(gè)interface似谁,我們稱這個(gè)實(shí)現(xiàn)為proxy類傲绣,通過proxy類調(diào)用你引用的第三方j(luò)ar。我們將這個(gè)規(guī)范interface單獨(dú)打成jar包放在主工程里巩踏,原理同上秃诵。
3.實(shí)現(xiàn)
創(chuàng)建一個(gè)規(guī)范interface,將其單獨(dú)導(dǎo)出一個(gè)jar塞琼,我們叫interface jar,放在主工程及你要導(dǎo)入的jar項(xiàng)目中:
導(dǎo)出時(shí)只選這個(gè)interface就行了:
由于我們需要將第三方j(luò)ar一起導(dǎo)出到一個(gè)jar中,還用這個(gè)方法導(dǎo)出的話我們無法將第三方j(luò)ar一起導(dǎo)入菠净,需要將引用的jar一起放入主工程才行,這違背了我們的初衷彪杉。這里我們用Idea編譯器毅往,新建一個(gè)項(xiàng)目DynamicLoadDemo,引用 interface jar派近,并實(shí)現(xiàn)ITest:
測試時(shí)我們引用 commons-io-2.2.jar 中的FileUtils煞抬,用來測試引用第三方j(luò)ar。
將我們的DynamicLoadDemo導(dǎo)出成一個(gè)jar:
這時(shí)候我們導(dǎo)出的jar并不包含dex文件构哺,需要我們用dx命令去處理革答,用命令行進(jìn)入你的sdk->build-tools目錄找到這個(gè)文件:
利用命令:
dx --dex --output=testjar1_temp.jar ?*\testJar1.jar ?
經(jīng)過處理后你的testjar1_temp.jar 中包含dex文件就可以用DexClassLoader加載其中的類了
新建一個(gè)測試項(xiàng)目DynamicLoadJar(主工程),引入interface jar,并將testjar1_temp.jar放在你的手機(jī)sd卡中,
DexClassLoader(java.lang.String dexPath, java.lang.String optimizedDirectory, java.lang.String libraryPath, java.lang.ClassLoader parent)
參數(shù)意義:
java.lang.String dexPath,? 需要裝載的APK或者Jar文件的路徑
java.lang.String optimizedDirectory, 優(yōu)化后的dex文件存放目錄战坤,不能為null
java.lang.String libraryPath,? 目標(biāo)類中使用的C/C++庫的列表, 可以為 null
?java.lang.ClassLoader parent? 該類裝載器的父裝載器,一般用當(dāng)前執(zhí)行類的裝載器
執(zhí)行結(jié)果:
完美残拐!