




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
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类的集合,此类适合大并发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();//判断系统是否是YunOs系统,YunOs系统是阿里巴巴的系统booleansetup=AndFix.setup();//判断是Dalvik还是Art虚拟机,来注册Native方法booleanisSupportSDKVersion=isSupportSDKVersion();//根据sdk版本判断是否支持if(!isYunOs&&setup&&isSupportSDKVersion){//根据上面三个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);//存储关于patch文件的信息//根据你传入的版本号和之前的对比,做不同的处理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文件加载到内存}}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实例存储到内存的集合中,在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());//根据反射获取到有bug的类的方法(有bug的apk)AndFix.addReplaceMethod(src,method);//src是有bug的方法,method是补丁方法}}catch(Exceptione){Log.e(TAG,"replaceMethod",e);}}publicstaticvoidaddReplaceMethod(Methodsrc,Methoddest){try{replaceMethod(src,dest);//调用了native方法,nextcodeinitFields(dest.getDeclaringClass());}catch(Throwablee){Log.e(TAG,"addReplaceMethod",e);}}privatestaticnativevoidreplaceMethod(Methoddest,Methodsrc);由于Android4.4后才用的Art虚拟机,之前的系统都是Dalvik虚拟机,因此Natice层写了2个方法,对不同的系统做不同的处理方式。externvoiddalvik_replaceMethod(JNIEnv*env,jobjectsrc,jobjectdest);//Dalvikexternvoidart_replaceMethod(JNIEnv*env,jobjectsrc,jobjectdest);//ArtDalvikreplaceMethod的实现: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;//把方法的实现替换成native方法}ArtreplaceMethod的实现://不同的art系统版本不同处理也不同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);//把一些参数的指针给补丁方法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. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 经费拨付协议书
- 绿化收购协议书
- 美伊谈判协议书
- 道路刷黑协议书
- 混凝土临时供货协议书
- 资金三方协议书
- 纱窗合作协议书
- 财务调账协议书
- 美女婚前协议书
- 拆迁后产权调换协议书
- 我国战略性金属和关键矿产发展白皮书-2025-05-宏观大势
- 2025年入团考试开放机会与试题与答案
- 电梯安全管理员培训
- 民办学校新学期课程设置计划
- ICU休克患者的镇痛镇静-秦秉玉
- 2025年高考数学复习难题速递之排列与组合(2025年4月)
- 森林抚育施工项目方案投标文件(技术方案)
- 北京开放大学2025年《企业统计》形考作业1答案
- 涉密项目管理培训
- 2025四川省安全员A证考试题库及答案
- 南开大学-商业健康保险与医药产业高质量协同发展-团体补充医疗保险改革新视角-2025年3月20日
评论
0/150
提交评论