Andfix学习记录Word文档下载推荐.docx

上传人:b****6 文档编号:8597934 上传时间:2023-05-12 格式:DOCX 页数:20 大小:276.31KB
下载 相关 举报
Andfix学习记录Word文档下载推荐.docx_第1页
第1页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第2页
第2页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第3页
第3页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第4页
第4页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第5页
第5页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第6页
第6页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第7页
第7页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第8页
第8页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第9页
第9页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第10页
第10页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第11页
第11页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第12页
第12页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第13页
第13页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第14页
第14页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第15页
第15页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第16页
第16页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第17页
第17页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第18页
第18页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第19页
第19页 / 共20页
Andfix学习记录Word文档下载推荐.docx_第20页
第20页 / 共20页
亲,该文档总共20页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Andfix学习记录Word文档下载推荐.docx

《Andfix学习记录Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《Andfix学习记录Word文档下载推荐.docx(20页珍藏版)》请在冰点文库上搜索。

Andfix学习记录Word文档下载推荐.docx

原理篇

andfix深入

补丁深入

andfix原理

andfix的核心原理就是方法替换在通过其apath工具给需要替换的方法加上注解@repleaceMethod,这样在执行时把有bug的方法替换成补丁文件中执行的方法。

(在Native层使用指针替换的方式替换bug的方法,从而达到修复bug的目的),具体过程如下图:

使用虚拟机的JarFile加载的补丁文件,读取PATCH.MF文件得到补丁类名称

获取补丁方法

使用DexFile读取patch文件的dex文件,获取后根据注解获取补丁方法

获取bug所在的方法

根据注解中获取到的类名和方法,使用ClassLaoder获取到class,然后根据反射得到bugMethod,并将其访问属性修改为public

—————————————–Java层————————————————————-

Native层替换方法

使用JNI来替换bug所在方法对象的属性来修复bug

简要类之间关系图

修复的具体过程为:

1)我们及时修复好bug之后,我们可以apkpatch工具将两个apk做一次对比,然后找出不同的部分。

生成的apatch了文件。

若果这个时候,我们把后缀改成zip再解压开,里面有一个dex文件。

反编译之后查看一下源码,里面就是被修复的代码所在的类文件,这些更改过的类都加上了一个_CF的后缀,并且变动的方法都被加上了一个叫@MethodReplace的annotation,通过clazz和method指定了需要替换的方法。

(后面补丁原理会说到)

2)客户端得到补丁文件后就会根据annotation来寻找需要替换的方法。

从AndFixManager.fix方法开始,客户端找到对应的需要替换的方法,然后在fix方法的具体实现中调用fixClass方法进行方法替换过程。

3)由JNI层完成方法的替换。

fixClass方法遍历补丁class里的方法,在jni层对所需要替换的方法进行一一替换。

(AndfixManager#replaceMethod)

源码解析

遵循使用时四步走:

Step1:

初始化PatchManger

`PatchManagerpatchManager=newPatchManager();

参阅patchManager类源码——>

AndfixManager其中包含了Compat兼容性检测类、SecurityChecker安全性检查类

`publicAndFixManager(Contextcontext){

mContext=context;

//判断机型是否支持Andfix阿里的YunOs不支持

mSupport=Compat.isSupport();

if(mSupport){

//初始化签名判断类

mSecurityChecker=newSecurityChecker(mContext);

mOptDir=newFile(mContext.getFilesDir(),DIR);

//makedirectoryfail

if(!

mOptDir.exists()&

&

!

mOptDir.mkdirs()){

mSupport=false;

Log.e(TAG,"

optdircreateerror."

);

}elseif(!

mOptDir.isDirectory()){//notdirectory

//如果不是目录则删除

mOptDir.delete();

}`

Step2:

使用PatchManger检查版本

`patchManager.init(apk版本)`

参阅patchManager#init——>

Patch构造函数初始化init

主要是版本比对,记录版本号;

根据版本号将patch清除或者加载到缓存中

参阅Patch#init

`publicvoidinit(StringappVersion){

mPatchDir.exists()&

mPatchDir.mkdirs()){//makedirectoryfail

patchdircreateerror."

return;

mPatchDir.isDirectory()){//notdirectory

mPatchDir.delete();

SharedPreferencessp=mContext.getSharedPreferences(SP_NAME,

Context.MODE_PRIVATE);

//缓存版本号

Stringver=sp.getString(SP_VERSION,null);

if(ver==null||!

ver.equalsIgnoreCase(appVersion)){

//根据传入版本号作对比,若不同,则删除本地的补丁文件

cleanPatch();

sp.edit().putString(SP_VERSION,appVersion).commit();

//传入新的版本号

}else{

initPatchs();

//初始化patch列表,把本地的patch加载到内存中

}

privatevoidinitPatchs(){

File[]files=mPatchDir.listFiles();

for(Filefile:

files){

addPatch(file);

Patch文件的加载使用JarFile读取Patch文件,读取一些属性如patchname,createtime,其中如果本地保存了多个补丁,那么AndFix会按照补丁生成的时间顺序加载补丁。

具体是根据.apatch文件中的PATCH.MF的字段Created-Time。

step3:

loadPatch

参阅patchManager#loadPatch

提供了3个重载方法

`publicvoidloadPatch()//andfix初始化之后调用

privatevoidloadPatch(Patchpatch)//下载补丁完成后调用,addPatch(path)

publicvoidloadPatch(StringpatchName,ClassLoaderclassLoader)//提供了自定义类加载器的实现

这三个核心都是调用了publicsynchronizedvoidfix(Filefile,ClassLoaderclassLoader,Listclasses)

参看AndfixManager#fix

`publicsynchronizedvoidfix(Filefile,ClassLoaderclassLoader,

List<

String>

classes){

mSupport){

//判断补丁的签名

mSecurityChecker.verifyApk(file)){//securitycheckfail

try{

Fileoptfile=newFile(mOptDir,file.getName());

booleansaveFingerprint=true;

if(optfile.exists()){

//needtoverifyfingerprintwhentheoptimizefileexist,

//preventsomeoneattackonjailbreakdevicewith

//Vulnerability-Parasyte.

//btw:

exaggeratedandroidVulnerability-Parasyte

//

//如果本地已经存在补丁文件,则校验指纹信息

if(mSecurityChecker.verifyOpt(optfile)){

saveFingerprint=false;

optfile.delete()){

//加载patch文件中的dex

finalDexFiledexFile=DexFile.loadDex(file.getAbsolutePath(),

optfile.getAbsolutePath(),Context.MODE_PRIVATE);

if(saveFingerprint){

mSecurityChecker.saveOptSig(optfile);

ClassLoaderpatchClassLoader=newClassLoader(classLoader){

//重写了ClassLoader的findClass方法

@Override

protectedClass<

?

>

findClass(StringclassName)

throwsClassNotFoundException{

Class<

clazz=dexFile.loadClass(className,this);

if(clazz==null

&

className.startsWith("

com.alipay.euler.andfix"

)){

returnClass.forName(className);

//annotation注解class

//notfound

if(clazz==null){

thrownewClassNotFoundException(className);

returnclazz;

};

Enumeration<

entrys=dexFile.entries();

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);

//核心-

}catch(IOExceptione){

pacth"

e);

fix——>

fixclass——>

replaceMethod——>

Andfix#replaceMethod(Methoddest,Methodsrc)Native方法

`privatevoidfixClass(Class<

clazz,ClassLoaderclassLoader){

//反射找到clazz中的所有方法

Method[]methods=clazz.getDeclaredMethods();

//MethodReplace的注解

MethodReplacemethodReplace;

Stringclz;

Stringmeth;

for(Methodmethod:

methods){

//遍历所有方法,找到有MethodReplace注解的方法,即需要替换的方法

methodReplace=method.getAnnotation(MethodReplace.class);

//获取此方法的注解,有bug的方法生成patch的类中的方法都是有注解的

if(methodReplace==null)

clz=methodReplace.clazz();

//获取注解中的clazz的值

meth=methodReplace.method();

//获取注解中method的值

isEmpty(clz)&

isEmpty(meth)){

//找到需要替换的方法后调用replaceMethod替换方法

replaceMethod(classLoader,clz,meth,method);

`privatevoidreplaceMethod(ClassLoaderclassLoader,Stringclz,

Stringmeth,Methodmethod){

Stringkey=clz+"

@"

+classLoader.toString();

//根据key查找缓存中的数据,该缓存记录了已经被修复过得class

clazz=mFixedClass.get(key);

if(clazz==null){//classnotload

//找不到说明该class没有被修复过,则通过类加载器去加载

clzz=classLoader.loadClass(clz);

//initializetargetclass

//通过C层改写accessFlag,把需要替换的类的所有方法(Field)改成了public

clazz=AndFix.initTargetClass(clzz);

//初始化targetclass

=null){//initializeclassOK

mFixedClass.put(key,clazz);

Methodsrc=clazz.getDeclaredMethod(meth,

method.getParameterTypes());

//根据反射拿到有bug的类的方法

//这里是调用了jni,art和dalvik分别执行不同的替换逻辑,在cpp进行实现

AndFix.addReplaceMethod(src,method);

//替换方法src是有bug的方法,method是补丁方法

}catch(Exceptione){

replaceMethod"

Natvie方法的分析见下面

前三步都是一开始初始化时候要做的,而最后一步第四步则是补丁下载好之后再做的

step4:

添加Patch

`patchManager.addPatch(path)`

参阅PatchManager#addPatch,最终还是执行loadpatch

appPatch——>

copy到andfix默认的文件夹下——>

执行loadPatch(补丁立即生效)

`publicvoidaddPatch(Stringpath)throwsIOException{

Filesrc=newFile(path);

Filedest=newFile(mPatchDir,src.getName());

if(!

src.exists()){

thrownewFileNotFoundException(path);

if(dest.exists()){

Log.d(TAG,"

patch["

+path+"

]hasbeloaded."

//这一步很重要,通过这一步将你所下载保存的patch文件,copy到andfix自己默认的文件夹内存的data/data/apatch

FileUtil.copyFile(src,dest);

//copytopatch'

sdirectory

Patchpatch=addPatch(dest);

if(patch!

//加载patch补丁立即生效

loadPatch(patch);

小结一下:

可以看出andfix的核心就是两大步

-java层实现加载补丁文件,安全验证等操作,然后根据补丁汇总的注解找到将要替换的方法,交给Native层去处理替换方法

-native层:

利用Javahook的技术来替换要修复的方法

附Native分析

在JNI目录下art和darvik文件中

andfix.cpp#replaceMethod——>

art_method_replace.cpp(根据版本)——art_method_replace_5_0.cpp

Dalvik

Dalvik是Google公司自己设计用于Android平台的Java虚拟机。

Dalvik虚拟机是Google等厂商合作开发的Android移动设备平台的核心组成部分之一。

它可以支持已转换为.dex(即DalvikExecutable)格式的Java应用程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。

Dalvik经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik应用作为一个独立的Linux进程执行。

独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。

ART

Android操作系统已经成熟,Google的Android团队开始将注意力转向一些底层组件,其中之一是负责应用程序运行的Dalvik运行时。

Google开发者已经花了两年时间开发更快执行效率更高更省电的替代ART运行时。

ART代表AndroidRuntime,其处理应用程序执行的方式完全不同于Dalvik,Dalvik是依靠一个Just-In-Time(JIT)编译器去解释字节码。

开发者编译后的应用代码需要通过一个解释器在用户的设备上运行,这一机制并不高效,但让应用能更容易在不同硬件和架构上运行。

ART则完全改变了这套做法,在应用安装时就预编译字节码到机器语言,这一机制叫Ahead-Of-Time(AOT)编译。

在移除解释代码这一过程后,应用程序执行将更有效率,启动更快。

-优缺点

ART优点:

1、系统性能的显著提升。

2、应用启动更快、运行更快、体验更流畅、触感反馈更及时。

3、更长的电池续航能力。

4、支持更低的硬件。

ART缺点:

1、更大的存储空间占用,可能会增加10%-20%。

2、更长的应用安装时间。

总的来说ART的功效就是“空间换时间”。

其他重要函数

PatchManage#removeAllPatch()

这个函数是在PatchManage#init(viersin)verision不同时调用的方法一样,清空补丁目录文件,这在做保护的时候十分重要。

`publicvoidremoveAllPatch(){

sp.edit().clear().commit();

比如在laodPatch,包括初始化的时候patchManager.loadPatch()和patchManager.addPatch(其实也是调用loadpath)

`publicvoidloadPatch(){

mLoaders.put("

*"

mContext.getClassLoader());

//wildcard

Set<

patchNames;

classes;

for(Patchpatch:

mPatchs){

patchNames=patch.getPatchNames();

for(StringpatchName:

patchNames){

classes=patch.getClasses(patchName);

//获取patch对用的class类集合

mAndFixMan

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > PPT模板 > 商务科技

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2