AndFix Bug熱修復框架原理及源碼解析_第1頁
AndFix Bug熱修復框架原理及源碼解析_第2頁
AndFix Bug熱修復框架原理及源碼解析_第3頁
AndFix Bug熱修復框架原理及源碼解析_第4頁
AndFix Bug熱修復框架原理及源碼解析_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

AndFixBug熱修復框架原理及源碼解析使用AndFix修復熱修復的整體流程:源碼解析解析源碼從使用的方法一一解析。在自定義Application中初始化PatchManger:PatchManagermPatchManager=newPatchManager();直接實例化了一個PatchManger實例對象,接下看PatchManager類源碼:publicPatchManager(Contextcontext){mContext=context;mAndFixManager=newAndFixManager(mContext);//初始化AndFixManagermPatchDir=newFile(mContext.getFilesDir(),DIR);//初始化存放patch補丁文件的文件夾mPatchs=newConcurrentSkipListSet<Patch>();//初始化存在Patch類的集合,此類適合大并發(fā)mLoaders=newConcurrentHashMap<String,ClassLoader>();//初始化存放類對應的類加載器集合}然后看AndFixManager的初始化:publicAndFixManager(Contextcontext){mContext=context;mSupport=Compat.isSupport();//判斷Android機型是否適支持AndFixif(mSupport){mSecurityChecker=newSecurityChecker(mContext);//初始化簽名判斷類mOptDir=newFile(mContext.getFilesDir(),DIR);//初始化patch文件存放的文件夾if(!mOptDir.exists()&&!mOptDir.mkdirs()){//makedirectoryfailmSupport=false;Log.e(TAG,"optdircreateerror.");}elseif(!mOptDir.isDirectory()){//notdirectorymOptDir.delete();//如果不是文件目錄就刪除mSupport=false;}}}publicstaticsynchronizedbooleanisSupport(){//此處加了同步鎖機制if(isChecked)returnisSupport;isChecked=true;//notsupportalibaba'sYunOsbooleanisYunOs=isYunOS();//判斷系統(tǒng)是否是YunOs系統(tǒng),YunOs系統(tǒng)是阿里巴巴的系統(tǒng)booleansetup=AndFix.setup();//判斷是Dalvik還是Art虛擬機,來注冊Native方法booleanisSupportSDKVersion=isSupportSDKVersion();//根據(jù)sdk版本判斷是否支持if(!isYunOs&&setup&&isSupportSDKVersion){//根據(jù)上面三個boolean值判斷是否支持isSupport=true;}if(inBlackList()){isSupport=false;}returnisSupport;}privatestaticbooleanisSupportSDKVersion(){if(android.os.Build.VERSION.SDK_INT>=8&&android.os.Build.VERSION.SDK_INT<=23){returntrue;}returnfalse;}publicstaticbooleansetup(){try{finalStringvmVersion=System.getProperty("java.vm.version");booleanisArt=vmVersion!=null&&vmVersion.startsWith("2");intapilevel=Build.VERSION.SDK_INT;returnsetup(isArt,apilevel);}catch(Exceptione){Log.e(TAG,"setup",e);returnfalse;}}//簽名機制的初始化過程publicSecurityChecker(Contextcontext){mContext=context;init(mContext);}//主要是獲取當前應用的簽名及其他信息,為了判斷與patch文件的簽名是否一致privatevoidinit(Contextcontext){try{PackageManagerpm=context.getPackageManager();StringpackageName=context.getPackageName();PackageInfopackageInfo=pm.getPackageInfo(packageName,PackageManager.GET_SIGNATURES);CertificateFactorycertFactory=CertificateFactory.getInstance("X.509");ByteArrayInputStreamstream=newByteArrayInputStream(packageInfo.signatures[0].toByteArray());X509Certificatecert=(X509Certificate)certFactory.generateCertificate(stream);mDebuggable=cert.getSubjectX500Principal().equals(DEBUG_DN);mPublicKey=cert.getPublicKey();}catch(NameNotFoundExceptione){Log.e(TAG,"init",e);}catch(CertificateExceptione){Log.e(TAG,"init",e);}}接下,看一下版本的初始化:mPatchManager.init("version")init方法源碼:publicvoidinit(StringappVersion){if(!mPatchDir.exists()&&!mPatchDir.mkdirs()){//makedirectoryfailLog.e(TAG,"patchdircreateerror.");return;}elseif(!mPatchDir.isDirectory()){//notdirectorymPatchDir.delete();return;}SharedPreferencessp=mContext.getSharedPreferences(SP_NAME,Context.MODE_PRIVATE);//存儲關(guān)于patch文件的信息//根據(jù)你傳入的版本號和之前的對比,做不同的處理Stringver=sp.getString(SP_VERSION,null);if(ver==null||!ver.equalsIgnoreCase(appVersion)){cleanPatch();//刪除本地patch文件sp.edit().putString(SP_VERSION,appVersion).commit();//并把傳入的版本號保存}else{initPatchs();//初始化patch列表,把本地的patch文件加載到內(nèi)存}}privatevoidcleanPatch(){File[]files=mPatchDir.listFiles();for(Filefile:files){mAndFixManager.removeOptFile(file);//刪除所有的本地緩存patch文件if(!FileUtil.deleteFile(file)){Log.e(TAG,file.getName()+"deleteerror.");}}}privatevoidinitPatchs(){File[]files=mPatchDir.listFiles();for(Filefile:files){addPatch(file);//加載Patch文件}}privatePatchaddPatch(Filefile){Patchpatch=null;if(file.getName().endsWith(SUFFIX)){try{patch=newPatch(file);//實例化Patch對象mPatchs.add(patch);//把patch實例存儲到內(nèi)存的集合中,在PatchManager實例化集合}catch(IOExceptione){Log.e(TAG,"addPatch",e);}}returnpatch;}Patch文件的加載publicPatch(Filefile)throwsIOException{mFile=file;init();}@SuppressWarnings("deprecation")privatevoidinit()throwsIOException{JarFilejarFile=null;InputStreaminputStream=null;try{jarFile=newJarFile(mFile);//使用JarFile讀取Patch文件JarEntryentry=jarFile.getJarEntry(ENTRY_NAME);//獲取META-INF/PATCH.MF文件inputStream=jarFile.getInputStream(entry);Manifestmanifest=newManifest(inputStream);Attributesmain=manifest.getMainAttributes();mName=main.getValue(PATCH_NAME);//獲取PATCH.MF屬性Patch-NamemTime=newDate(main.getValue(CREATED_TIME));//獲取PATCH.MF屬性Created-TimemClassesMap=newHashMap<String,List<String>>();Attributes.NameattrName;Stringname;List<String>strings;for(Iterator<?>it=main.keySet().iterator();it.hasNext();){attrName=(Attributes.Name)it.next();name=attrName.toString();//判斷name的后綴是否是-Classes,并把name對應的值加入到集合中,對應的值就是class類名的列表if(name.endsWith(CLASSES)){strings=Arrays.asList(main.getValue(attrName).split(","));if(name.equalsIgnoreCase(PATCH_CLASSES)){mClassesMap.put(mName,strings);}else{mClassesMap.put(name.trim().substring(0,name.length()-8),//remove//"-Classes"strings);}}}}finally{if(jarFile!=null){jarFile.close();}if(inputStream!=null){inputStream.close();}}}loadPatch方法源碼mPatchManager.loadPatch();loadPatch源碼:publicvoidloadPatch(){mLoaders.put("*",mContext.getClassLoader());//wildcardSet<String>patchNames;List<String>classes;for(Patchpatch:mPatchs){patchNames=patch.getPatchNames();for(StringpatchName:patchNames){classes=patch.getClasses(patchName);//獲取patch對用的class類的集合ListmAndFixManager.fix(patch.getFile(),mContext.getClassLoader(),classes);//修復bug方法}}}fixbugpublicsynchronizedvoidfix(Filefile,ClassLoaderclassLoader,List<String>classes){if(!mSupport){return;}//判斷patch文件的簽名if(!mSecurityChecker.verifyApk(file)){//securitycheckfailreturn;}try{Fileoptfile=newFile(mOptDir,file.getName());booleansaveFingerprint=true;if(optfile.exists()){//needtoverifyfingerprintwhentheoptimizefileexist,//preventsomeoneattackonjailbreakdevicewith//Vulnerability-Parasyte.//btw:exaggeratedandroidVulnerability-Parasyte///Exaggerated-Android-Vulnerability-Parasyte.htmlif(mSecurityChecker.verifyOpt(optfile)){saveFingerprint=false;}elseif(!optfile.delete()){return;}}//加載patch文件中的dexfinalDexFiledexFile=DexFile.loadDex(file.getAbsolutePath(),optfile.getAbsolutePath(),Context.MODE_PRIVATE);if(saveFingerprint){mSecurityChecker.saveOptSig(optfile);}ClassLoaderpatchClassLoader=newClassLoader(classLoader){@OverrideprotectedClass<?>findClass(StringclassName)throwsClassNotFoundException{//重寫ClasLoader的findClass方法Class<?>clazz=dexFile.loadClass(className,this);if(clazz==null&&className.startsWith("com.alipay.euler.andfix")){returnClass.forName(className);//annotation’sclass//notfound}if(clazz==null){thrownewClassNotFoundException(className);}returnclazz;}};Enumeration<String>entrys=dexFile.entries();Class<?>clazz=null;while(entrys.hasMoreElements()){Stringentry=entrys.nextElement();if(classes!=null&&!classes.contains(entry)){continue;//skip,notneedfix}clazz=dexFile.loadClass(entry,patchClassLoader);//獲取有bug的類文件if(clazz!=null){fixClass(clazz,classLoader);//nextcode}}}catch(IOExceptione){Log.e(TAG,"pacth",e);}}privatevoidfixClass(Class<?>clazz,ClassLoaderclassLoader){Method[]methods=clazz.getDeclaredMethods();MethodReplacemethodReplace;Stringclz;Stringmeth;for(Methodmethod:methods){//獲取此方法的注解,因為有bug的方法在生成的patch的類中的方法都是有注解的,下面會給圖進行展示methodReplace=method.getAnnotation(MethodReplace.class);if(methodReplace==null)continue;clz=methodReplace.clazz();//獲取注解中clazz的值meth=methodReplace.method();//獲取注解中method的值if(!isEmpty(clz)&&!isEmpty(meth)){replaceMethod(classLoader,clz,meth,method);//nextcode}}}privatevoidreplaceMethod(ClassLoaderclassLoader,Stringclz,Stringmeth,Methodmethod){try{Stringkey=clz+"@"+classLoader.toString();Class<?>clazz=mFixedClass.get(key);//判斷此類是否被fixif(clazz==null){//classnotloadClass<?>clzz=classLoader.loadClass(clz);//initializetargetclassclazz=AndFix.initTargetClass(clzz);//初始化class}if(clazz!=null){//initializeclassOKmFixedClass.put(key,clazz);Methodsrc=clazz.getDeclaredMethod(meth,method.getParameterTypes());//根據(jù)反射獲取到有bug的類的方法(有bug的apk)AndFix.addReplaceMethod(src,method);//src是有bug的方法,method是補丁方法}}catch(Exceptione){Log.e(TAG,"replaceMethod",e);}}publicstaticvoidaddReplaceMethod(Methodsrc,Methoddest){try{replaceMethod(src,dest);//調(diào)用了native方法,nextcodeinitFields(dest.getDeclaringClass());}catch(Throwablee){Log.e(TAG,"addReplaceMethod",e);}}privatestaticnativevoidreplaceMethod(Methoddest,Methodsrc);由于Android4.4后才用的Art虛擬機,之前的系統(tǒng)都是Dalvik虛擬機,因此Natice層寫了2個方法,對不同的系統(tǒng)做不同的處理方式。externvoiddalvik_replaceMethod(JNIEnv*env,jobjectsrc,jobjectdest);//Dalvikexternvoidart_replaceMethod(JNIEnv*env,jobjectsrc,jobjectdest);//ArtDalvikreplaceMethod的實現(xiàn):externvoid__attribute__((visibility("hidden")))dalvik_replaceMethod(JNIEnv*env,jobjectsrc,ectdest){jobjectclazz=env->CallObjectMethod(dest,jClassMethod);ClassObject*clz=(ClassObject*)dvmDecodeIndirectRef_fnPtr(dvmThreadSelf_fnPtr(),clazz);clz->status=CLASS_INITIALIZED;Method*meth=(Method*)env->FromReflectedMethod(src);Method*target=(Method*)env->FromReflectedMethod(dest);LOGD("dalvikMethod:%s",meth->name);meth->jniArgInfo=0x80000000;meth->accessFlags|=ACC_NATIVE;//把Method的屬性設置成Native方法intargsSize=dvmComputeMethodArgsSize_fnPtr(meth);if(!dvmIsStaticMethod(meth))argsSize++;meth->registersSize=meth->insSize=argsSize;meth->insns=(void*)target;meth->nativeFunc=dalvik_dispatcher;//把方法的實現(xiàn)替換成native方法}ArtreplaceMethod的實現(xiàn)://不同的art系統(tǒng)版本不同處理也不同externvoid__attribute__((visibility("hidden")))art_replaceMethod(JNIEnv*env,jobjectsrc,jobjectdest){if(apilevel>22){replace_6_0(env,src,dest);}elseif(apilevel>21){replace_5_1(env,src,dest);}else{replace_5_0(env,src,dest);}}//以5.0為例:voidreplace_5_0(JNIEnv*env,jobjectsrc,jobjectdest){art::mirror::ArtMethod*smeth=(art::mirror::ArtMethod*)env->FromReflectedMethod(src);art::mirror::ArtMethod*dmeth=(art::mirror::ArtMethod*)env->FromReflectedMethod(dest);dmeth->declaring_class_->class_loader_=smeth->declaring_class_->class_loader_;//forpluginclassloaderdmeth->declaring_class_->clinit_thread_id_=smeth->declaring_class_->clinit_thread_id_;dmeth->declaring_class_->status_=(void*)((int)smeth->declaring_class_->status_-1);//把一些參數(shù)的指針給補丁方法smeth->declaring_class_=dmeth->declaring_class_;smeth->access_flags_=dmeth->access_flags_;smeth->frame_size_in_bytes_=dmeth->frame_size_in_bytes_;smeth->dex_cache_initialized_static_storage_=dmeth->dex_cache_initialized_static_storage_;smeth->dex_cache_resolved_types_=dmeth->dex_cache_resolved_types_;smeth->dex_cache_resolved_methods_=dmeth->dex_cache_resolved_methods_;smeth->vmap_table_=dmeth->vmap_table_;smeth->core_spill_mask_=dmeth->core_spil

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論