08 原始碼閱讀(阿里AndFix熱修復原理)

2021-09-20 01:16:37 字數 2931 閱讀 8281

使用阿里熱修復需要新增依賴

compile 'com.alipay.euler:andfix:0.5.0@aar'
熱修復的關鍵**

//初始化阿里熱修復

mpatchmanger = new patchmanager(this);

//獲取當前應用版本

mpatchmanger.loadpatch();

file patchfile = new file(environment.getexternalstoragedirectory().getabsolutepath(),"fix.apatch");

if (patchfile != null) catch (ioexception e)

}

接下來我們從這些方法開始看熱修復是怎樣實現的

mpatchmanger = new patchmanager(this);

public patchmanager(context context)
if (!mpatchdir.exists() && !mpatchdir.mkdirs()) else if (!mpatchdir.isdirectory())

sharedpreferences sp = mcontext.getsharedpreferences(sp_name,

context.mode_private);

string ver = sp.getstring(sp_version, null);

//版本校驗

cleanpatch();

} else

}

private void initpatchs() 

}

addpatch

驗證檔名,對符合要求的檔名進行封裝,得到乙個個patch物件,在集合中儲存

/**

* add patch file

* * @param file

* @return patch

*/private patch addpatch(file file) catch (ioexception e)

}return patch;

}

可見mpatchmanger.init方法只是載入差分包然後進行儲存

接下來看mpatchmanger.loadpatch();

public void loadpatch() }}

進入mandfixmanager.fix(patch.getfile(),mcontext.getclassloader(),

classes);

//listclasses儲存了每個patc**件的相關資訊

public synchronized void fix(file file, classloader classloader,

listclasses)

if (clazz == null)

return clazz;}};

enumerationentrys = dexfile.entries();

class> clazz = null;

while (entrys.hasmoreelements())

//通過classloader載入得到差分包中的修復了的class

clazz = dexfile.loadclass(entry, patchclassloader);

if (clazz != null)

}} catch (ioexception e)

}

fixclass

看到下邊也許覺得奇怪,為什麼去獲取了乙個叫methodreplace的註解呢,這個註解是在**使用的,有什麼作用,

private void fixclass(class> clazz, classloader classloader) }}

解壓差分包我們可以看到andfix在發生錯誤的位置做了標記,就是這個註解

在錯誤的方法上新增註解,看上邊遍歷這個class檔案中所有的方法,找到這個註解呼叫replacemethod,故名思意,就是將錯誤的方法替換為正確的方法,有可能是存在多個class存在多個問題,其實andfix修復的原理就是解壓生成的patch.mf檔案,這個檔案中儲存了有錯誤的類的資訊,把這些類加入集合,遍歷集合通過上邊的方式獲取到註解,定位到錯誤的位置

private void replacemethod(classloader classloader, string clz,

string meth, method method)

if (clazz != null)

} catch (exception e)

}

public static void addreplacemethod(method src, method dest)  catch (throwable e) 

}

最後可以看到這裡已經是c層面的做法了

可以看到其實native層是通過指標修改方法的指向實現修復問題的,指向正確的修復之後的方法,就是這樣,ok了

《原始碼閱讀》原始碼閱讀技巧,原始碼閱讀工具

檢視某個類的完整繼承關係 選中類的名稱,然後按f4 quick type hierarchy quick type hierarchy可以顯示出類的繼承結構,包括它的父類和子類 supertype hierarchy supertype hierarchy可以顯示出類的繼承和實現結構,包括它的父類和...

原始碼閱讀 Glide原始碼閱讀之with方法(一)

前言 本篇基於4.8.0版本 原始碼閱讀 glide原始碼閱讀之with方法 一 原始碼閱讀 glide原始碼閱讀之load方法 二 原始碼閱讀 glide原始碼閱讀之into方法 三 大多數情況下,我們使用glide 就一句 但是這一句 裡面蘊含著成噸的 with方法有以下幾個過載方法 publi...

原始碼閱讀 Glide原始碼閱讀之load方法(二)

原始碼閱讀 glide原始碼閱讀之load方法 二 原始碼閱讀 glide原始碼閱讀之into方法 三 首先,load方法有以下幾個過載方法 public requestbuilder load nullable bitmap bitmap public requestbuilder load nu...