日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Alibaba-AndFix Bug热修复框架原理及源码解析

發(fā)布時間:2025/3/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Alibaba-AndFix Bug热修复框架原理及源码解析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

小憩之后,繼續(xù)為你解讀AndFix熱修復(fù)框架,呵呵。

上一篇Alibaba-AndFix Bug熱修復(fù)框架的使用已經(jīng)介紹了AndFix的使用,這篇主要介紹AndFix原理以及源碼解析。

    • AndFix原理
    • 源碼解析
      • 在自定義Application中初始化PatchManger
      • init方法源碼
        • Patch文件的加載
      • loadPatch方法源碼
        • fix bug
        • Dalvik replaceMethod的實(shí)現(xiàn)
        • Art replaceMethod的實(shí)現(xiàn)
      • 添加Patch
      • 移除Patch
    • 反編譯Patch dex文件代碼

AndFix原理

AndFix的原理就是方法的替換,把有bug的方法替換成補(bǔ)丁文件中的方法。?

注:在Native層使用指針替換的方式替換bug方法,已達(dá)到修復(fù)bug的目的。

使用AndFix修復(fù)熱修復(fù)的整體流程:

方法替換過程:

源碼解析

解析源碼從使用的方法一一解析。

在自定義Application中初始化PatchManger:

<code class="hljs fix has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-attribute" style="box-sizing: border-box;">PatchManager mPatchManager </span>=<span class="hljs-string" style="color:#0880;box-sizing: border-box;"> new PatchManager();</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

直接實(shí)例化了一個PatchManger實(shí)例對象,接下看PatchManager類源碼:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">PatchManager</span>(Context context) {mContext = context;mAndFixManager = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> AndFixManager(mContext);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//初始化AndFixManager</span>mPatchDir = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(mContext.getFilesDir(), DIR);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//初始化存放patch補(bǔ)丁文件的文件夾</span>mPatchs = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> ConcurrentSkipListSet<Patch>();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//初始化存在Patch類的集合,此類適合大并發(fā)</span>mLoaders = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> ConcurrentHashMap<String, ClassLoader>();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//初始化存放類對應(yīng)的類加載器集合</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

然后看AndFixManager的初始化:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">AndFixManager</span>(Context context) {mContext = context;mSupport = Compat.isSupport();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//判斷Android機(jī)型是否適支持AndFix</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (mSupport) {mSecurityChecker = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> SecurityChecker(mContext);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//初始化簽名判斷類</span>mOptDir = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(mContext.getFilesDir(), DIR);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//初始化patch文件存放的文件夾</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!mOptDir.exists() && !mOptDir.mkdirs()) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// make directory fail</span>mSupport = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;Log.e(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"opt dir create error."</span>);} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!mOptDir.isDirectory()) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// not directory</span>mOptDir.delete();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//如果不是文件目錄就刪除</span>mSupport = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;}} } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">synchronized</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">isSupport</span>() {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//此處加了同步鎖機(jī)制</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (isChecked)<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> isSupport;isChecked = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>;<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// not support alibaba's YunOs</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> isYunOs = isYunOS();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//判斷系統(tǒng)是否是YunOs系統(tǒng),YunOs系統(tǒng)是阿里巴巴的系統(tǒng)</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> setup =AndFix.setup();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//判斷是Dalvik還是Art虛擬機(jī),來注冊Native方法</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> isSupportSDKVersion = isSupportSDKVersion();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//根據(jù)sdk版本判斷是否支持</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!isYunOs && setup && isSupportSDKVersion) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//根據(jù)上面三個boolean值判斷是否支持</span>isSupport = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>;}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (inBlackList()) {isSupport = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> isSupport; } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">isSupportSDKVersion</span>() {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (android.os.Build.VERSION.SDK_INT >= <span class="hljs-number" style="color:#06666;box-sizing: border-box;">8</span>&& android.os.Build.VERSION.SDK_INT <= <span class="hljs-number" style="color:#06666;box-sizing: border-box;">23</span>) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>;}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>; } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">setup</span>() {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> String vmVersion = System.getProperty(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"java.vm.version"</span>);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> isArt = vmVersion != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span> && vmVersion.startsWith(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"2"</span>);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> apilevel = Build.VERSION.SDK_INT;<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> setup(isArt, apilevel);} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (Exception e) {Log.e(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"setup"</span>, e);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;} } <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//簽名機(jī)制的初始化過程</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">SecurityChecker</span>(Context context) {mContext = context;init(mContext); } <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//主要是獲取當(dāng)前應(yīng)用的簽名及其他信息,為了判斷與patch文件的簽名是否一致</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">init</span>(Context context) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {PackageManager pm = context.getPackageManager();String packageName = context.getPackageName();PackageInfo packageInfo = pm.getPackageInfo(packageName,PackageManager.GET_SIGNATURES);CertificateFactory certFactory = CertificateFactory.getInstance(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"X.509"</span>);ByteArrayInputStream stream = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> ByteArrayInputStream(packageInfo.signatures[<span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>].toByteArray());X509Certificate cert = (X509Certificate) certFactory.generateCertificate(stream);mDebuggable = cert.getSubjectX500Principal().equals(DEBUG_DN);mPublicKey = cert.getPublicKey();} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (NameNotFoundException e) {Log.e(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"init"</span>, e);} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (CertificateException e) {Log.e(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"init"</span>, e);} }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li></ul>

接下,看一下版本的初始化:

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">mPatchManager<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">.init</span>(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"version"</span>)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

init方法源碼:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">init</span>(String appVersion) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!mPatchDir.exists() && !mPatchDir.mkdirs()) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// make directory fail</span>Log.e(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"patch dir create error."</span>);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!mPatchDir.isDirectory()) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// not directory</span>mPatchDir.delete();<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;}SharedPreferences sp = mContext.getSharedPreferences(SP_NAME,Context.MODE_PRIVATE);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//存儲關(guān)于patch文件的信息</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//根據(jù)你傳入的版本號和之前的對比,做不同的處理</span>String ver = sp.getString(SP_VERSION, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (ver == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span> || !ver.equalsIgnoreCase(appVersion)) {cleanPatch();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//刪除本地patch文件</span>sp.edit().putString(SP_VERSION, appVersion).commit();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//并把傳入的版本號保存</span>} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {initPatchs();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//初始化patch列表,把本地的patch文件加載到內(nèi)存</span>} }<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">cleanPatch</span>() {File[] files = mPatchDir.listFiles();<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">for</span> (File file : files) {mAndFixManager.removeOptFile(file);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//刪除所有的本地緩存patch文件</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!FileUtil.deleteFile(file)) {Log.e(TAG, file.getName() + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">" delete error."</span>);}} } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">initPatchs</span>() {File[] files = mPatchDir.listFiles();<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">for</span> (File file : files) {addPatch(file);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//加載Patch文件</span>} } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> Patch <span class="hljs-title" style="box-sizing: border-box;">addPatch</span>(File file) {Patch patch = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>;<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (file.getName().endsWith(SUFFIX)) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {patch = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> Patch(file);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//實(shí)例化Patch對象</span>mPatchs.add(patch);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把patch實(shí)例存儲到內(nèi)存的集合中,在PatchManager實(shí)例化集合</span>} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (IOException e) {Log.e(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"addPatch"</span>, e);}}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> patch; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li></ul>

Patch文件的加載

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Patch</span>(File file) <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> IOException {mFile = file;init(); }<span class="hljs-annotation" style="color:#9b859d;box-sizing: border-box;">@SuppressWarnings</span>(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"deprecation"</span>) <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">init</span>() <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> IOException {JarFile jarFile = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>;InputStream inputStream = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>;<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {jarFile = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> JarFile(mFile);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//使用JarFile讀取Patch文件</span>JarEntry entry = jarFile.getJarEntry(ENTRY_NAME);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//獲取META-INF/PATCH.MF文件</span>inputStream = jarFile.getInputStream(entry);Manifest manifest = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> Manifest(inputStream);Attributes main = manifest.getMainAttributes();mName = main.getValue(PATCH_NAME);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//獲取PATCH.MF屬性Patch-Name</span>mTime = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> Date(main.getValue(CREATED_TIME));<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//獲取PATCH.MF屬性Created-Time</span>mClassesMap = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> HashMap<String, List<String>>();Attributes.Name attrName;String name;List<String> strings;<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">for</span> (Iterator<?> it = main.keySet().iterator(); it.hasNext();) {attrName = (Attributes.Name) it.next();name = attrName.toString();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//判斷name的后綴是否是-Classes,并把name對應(yīng)的值加入到集合中,對應(yīng)的值就是class類名的列表</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (name.endsWith(CLASSES)) {strings = Arrays.asList(main.getValue(attrName).split(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">","</span>));<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (name.equalsIgnoreCase(PATCH_CLASSES)) {mClassesMap.put(mName, strings);} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {mClassesMap.put(name.trim().substring(<span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>, name.length() - <span class="hljs-number" style="color:#06666;box-sizing: border-box;">8</span>),<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// remove</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// "-Classes"</span>strings);}}}} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">finally</span> {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (jarFile != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {jarFile.close();}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (inputStream != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {inputStream.close();}}}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li></ul>

loadPatch方法源碼

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">mPatchManager<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">.loadPatch</span>()<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

loadPatch源碼:

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">void</span> loadPatch() {mLoaders<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>put(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"*"</span>, mContext<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>getClassLoader());<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// wildcard</span><span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">Set</span><span class="hljs-subst" style="color:#000000;box-sizing: border-box;"><</span><span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">String</span><span class="hljs-subst" style="color:#000000;box-sizing: border-box;">></span> patchNames;<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">List</span><span class="hljs-subst" style="color:#000000;box-sizing: border-box;"><</span><span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">String</span><span class="hljs-subst" style="color:#000000;box-sizing: border-box;">></span> classes;for (Patch patch : mPatchs) {patchNames <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> patch<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>getPatchNames();for (<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">String</span> patchName : patchNames) {classes <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> patch<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>getClasses(patchName);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//獲取patch對用的class類的集合List</span>mAndFixManager<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>fix(patch<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>getFile(), mContext<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>getClassLoader(),classes);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//修復(fù)bug方法</span>}} }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

fix bug

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">synchronized</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fix</span>(File file, ClassLoader classLoader,List<String> classes) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!mSupport) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;}<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//判斷patch文件的簽名</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!mSecurityChecker.verifyApk(file)) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// security check fail</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {File optfile = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(mOptDir, file.getName());<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> saveFingerprint = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>;<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (optfile.exists()) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// need to verify fingerprint when the optimize file exist,</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// prevent someone attack on jailbreak device with</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Vulnerability-Parasyte.</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// btw:exaggerated android Vulnerability-Parasyte</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// http://secauo.com/Exaggerated-Android-Vulnerability-Parasyte.html</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (mSecurityChecker.verifyOpt(optfile)) {saveFingerprint = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!optfile.delete()) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;}}<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//加載patch文件中的dex</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">final</span> DexFile dexFile = DexFile.loadDex(file.getAbsolutePath(),optfile.getAbsolutePath(), Context.MODE_PRIVATE);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (saveFingerprint) {mSecurityChecker.saveOptSig(optfile);}ClassLoader patchClassLoader = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> ClassLoader(classLoader) {<span class="hljs-annotation" style="color:#9b859d;box-sizing: border-box;">@Override</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">protected</span> Class<?> <span class="hljs-title" style="box-sizing: border-box;">findClass</span>(String className)<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> ClassNotFoundException {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//重寫ClasLoader的findClass方法</span>Class<?> clazz = dexFile.loadClass(className, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</span>);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (clazz == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>&& className.startsWith(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"com.alipay.euler.andfix"</span>)) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> Class.forName(className);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// annotation’s class</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// not found</span>}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (clazz == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> ClassNotFoundException(className);}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> clazz;}};Enumeration<String> entrys = dexFile.entries();Class<?> clazz = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>;<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">while</span> (entrys.hasMoreElements()) {String entry = entrys.nextElement();<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (classes != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span> && !classes.contains(entry)) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">continue</span>;<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// skip, not need fix</span>}clazz = dexFile.loadClass(entry, patchClassLoader);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//獲取有bug的類文件</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (clazz != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {fixClass(clazz, classLoader);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// next code</span>}}} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (IOException e) {Log.e(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"pacth"</span>, e);} } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">fixClass</span>(Class<?> clazz, ClassLoader classLoader) {Method[] methods = clazz.getDeclaredMethods();MethodReplace methodReplace;String clz;String meth;<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">for</span> (Method method : methods) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//獲取此方法的注解,因?yàn)橛衎ug的方法在生成的patch的類中的方法都是有注解的,下面會給圖進(jìn)行展示</span>methodReplace = method.getAnnotation(MethodReplace.class);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (methodReplace == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>)<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">continue</span>;clz = methodReplace.clazz();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//獲取注解中clazz的值</span>meth = methodReplace.method();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//獲取注解中method的值</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!isEmpty(clz) && !isEmpty(meth)) {replaceMethod(classLoader, clz, meth, method);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//next code</span>}} } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">replaceMethod</span>(ClassLoader classLoader, String clz,String meth, Method method) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {String key = clz + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"@"</span> + classLoader.toString();Class<?> clazz = mFixedClass.get(key);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//判斷此類是否被fix</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (clazz == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// class not load</span>Class<?> clzz = classLoader.loadClass(clz);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// initialize target class</span>clazz = AndFix.initTargetClass(clzz);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//初始化class</span>}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (clazz != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// initialize class OK</span>mFixedClass.put(key, clazz);Method src = clazz.getDeclaredMethod(meth,method.getParameterTypes());<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//根據(jù)反射獲取到有bug的類的方法(有bug的apk)</span>AndFix.addReplaceMethod(src, method);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//src是有bug的方法,method是補(bǔ)丁方法</span>}} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (Exception e) {Log.e(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"replaceMethod"</span>, e);} } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">addReplaceMethod</span>(Method src, Method dest) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {replaceMethod(src, dest);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//調(diào)用了native方法,next code</span>initFields(dest.getDeclaringClass());} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (Throwable e) {Log.e(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"addReplaceMethod"</span>, e);} } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">native</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">replaceMethod</span>(Method dest, Method src);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li></ul>

由于Android4.4后才用的Art虛擬機(jī),之前的系統(tǒng)都是Dalvik虛擬機(jī),因此Natice層寫了2個方法,對不同的系統(tǒng)做不同的處理方式。

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">extern</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> dalvik_replaceMethod(JNIEnv* env, jobject src, jobject dest);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//Dalvik</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">extern</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> art_replaceMethod(JNIEnv* env, jobject src, jobject dest);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//Art</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

Dalvik replaceMethod的實(shí)現(xiàn):

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">extern <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">void</span> __attribute__ ((visibility (<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"hidden"</span>))) dalvik_replaceMethod(JNIEnv<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span> env, jobject src, jobject dest) {jobject clazz <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> env<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>CallObjectMethod(dest, jClassMethod);ClassObject<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span> clz <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> (ClassObject<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span>) dvmDecodeIndirectRef_fnPtr(dvmThreadSelf_fnPtr(), clazz);clz<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>status <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> CLASS_INITIALIZED;Method<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span> meth <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> (Method<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span>) env<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>FromReflectedMethod(src);Method<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span> target <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> (Method<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span>) env<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>FromReflectedMethod(dest);LOGD(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"dalvikMethod: %s"</span>, meth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>name);meth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>jniArgInfo <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0x80000000</span>;meth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>accessFlags <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">|=</span> ACC_NATIVE;<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把Method的屬性設(shè)置成Native方法</span>int argsSize <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dvmComputeMethodArgsSize_fnPtr(meth);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">!</span>dvmIsStaticMethod(meth))argsSize<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">++</span>;meth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>registersSize <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> meth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>insSize <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> argsSize;meth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>insns <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> (<span class="hljs-literal" style="color:#06666;box-sizing: border-box;">void</span><span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span>) target;meth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>nativeFunc <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dalvik_dispatcher;<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把方法的實(shí)現(xiàn)替換成native方法</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li></ul>

Art replaceMethod的實(shí)現(xiàn):

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//不同的art系統(tǒng)版本不同處理也不同</span> extern <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">void</span> __attribute__ ((visibility (<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"hidden"</span>))) art_replaceMethod(JNIEnv<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span> env, jobject src, jobject dest) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (apilevel <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">></span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">22</span>) {replace_6_0(env, src, dest);} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (apilevel <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">></span> <span class="hljs-number" style="color:#06666;box-sizing: border-box;">21</span>) {replace_5_1(env, src, dest);} <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {replace_5_0(env, src, dest);} } <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//以5.0為例:</span> <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">void</span> replace_5_0(JNIEnv<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span> env, jobject src, jobject dest) {art<span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::mirror</span><span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::ArtMethod</span><span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span> smeth <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span>(art<span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::mirror</span><span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::ArtMethod</span><span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span>) env<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>FromReflectedMethod(src);art<span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::mirror</span><span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::ArtMethod</span><span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span> dmeth <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span>(art<span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::mirror</span><span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::ArtMethod</span><span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span>) env<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>FromReflectedMethod(dest);dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>declaring_class_<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>class_loader_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span>smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>declaring_class_<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>class_loader_; <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//for plugin classloader</span>dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>declaring_class_<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>clinit_thread_id_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span>smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>declaring_class_<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>clinit_thread_id_;dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>declaring_class_<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>status_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> (<span class="hljs-literal" style="color:#06666;box-sizing: border-box;">void</span> <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span>)((int)smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>declaring_class_<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>status_<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-</span><span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把一些參數(shù)的指針給補(bǔ)丁方法</span>smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>declaring_class_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>declaring_class_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>access_flags_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>access_flags_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>frame_size_in_bytes_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>frame_size_in_bytes_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>dex_cache_initialized_static_storage_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span>dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>dex_cache_initialized_static_storage_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>dex_cache_resolved_types_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>dex_cache_resolved_types_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>dex_cache_resolved_methods_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>dex_cache_resolved_methods_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>vmap_table_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>vmap_table_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>core_spill_mask_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>core_spill_mask_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>fp_spill_mask_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>fp_spill_mask_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>mapping_table_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>mapping_table_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>code_item_offset_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>code_item_offset_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>entry_point_from_compiled_code_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span>dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>entry_point_from_compiled_code_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>entry_point_from_interpreter_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>entry_point_from_interpreter_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>native_method_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>native_method_;<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把補(bǔ)丁方法替換掉</span>smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>method_index_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>method_index_;smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>method_dex_index_ <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>method_dex_index_;LOGD(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"replace_5_0: %d , %d"</span>, smeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>entry_point_from_compiled_code_,dmeth<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">-></span>entry_point_from_compiled_code_);}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li></ul>

添加Patch

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">mPatchManager<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">.addPatch</span>(path)</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

源碼:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">addPatch</span>(String path) <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> IOException {File src = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(path);File dest = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> File(mPatchDir, src.getName());<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!src.exists()) {<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throw</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> FileNotFoundException(path);}<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (dest.exists()) {Log.d(TAG, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"patch ["</span> + path + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"] has be loaded."</span>);<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;}FileUtil.copyFile(src, dest);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// copy to patch's directory</span>Patch patch = addPatch(dest);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//同loadPatch中的addPatch一樣的操作</span><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (patch != <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {loadPatch(patch);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//加載pach,同上loadPatch</span>}}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

移除Patch

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">mPatchManager<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">.removeAllPatch</span>()<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

源碼:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">removeAllPatch</span>() {cleanPatch();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//刪除本地緩存的patch文件列表</span>SharedPreferences sp = mContext.getSharedPreferences(SP_NAME,Context.MODE_PRIVATE);sp.edit().clear().commit();<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把關(guān)于patch的數(shù)據(jù)進(jìn)行清空</span>}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

到此源代碼就解析結(jié)束。

反編譯Patch dex文件代碼

patch文件中.dex文件反編譯后,看到源碼效果如下:?
?
紅框標(biāo)注的部分,就是補(bǔ)丁方法。方法的注解部分寫了clazz和method的值,對應(yīng)著apk包中的類名和方法名稱。


原文地址: http://blog.csdn.net/qxs965266509/article/details/49816007

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的Alibaba-AndFix Bug热修复框架原理及源码解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

97在线成人 | 日韩精品免费一区 | 国产精品va在线观看入 | 久久久国产精品人人片99精片欧美一 | av电影在线观看完整版一区二区 | 亚洲视频综合在线 | 久久超碰免费 | 中文字幕视频播放 | 免费日韩一区二区三区 | 在线午夜| 三级黄色在线观看 | 国产精品99久久久久久久久久久久 | 一区二区国产精品 | 狠狠的操狠狠的干 | 成人av一区二区兰花在线播放 | 亚洲国产精品日韩 | 少妇视频一区 | 麻花豆传媒mv在线观看网站 | 开心激情五月婷婷 | 五月激情亚洲 | 91欧美视频网站 | 欧美精彩视频在线观看 | 久久在现 | 亚洲第一av在线播放 | 国产精品久久一卡二卡 | 高清色免费 | 日韩高清国产精品 | 手机av在线不卡 | 激情av在线资源 | 一区二区三区免费在线观看视频 | 久久99精品久久久久久 | 欧美在线不卡一区 | 97在线视 | 国产在线 一区二区三区 | 9797在线看片亚洲精品 | 免费看久久 | 中文成人字幕 | 丁香综合激情 | 天天草天天色 | 久久久久久久福利 | 久久国产精品精品国产色婷婷 | 日本黄色免费观看 | 久久精彩免费视频 | 日韩av不卡在线播放 | 成片视频免费观看 | 午夜精品久久久99热福利 | 久久综合狠狠综合久久激情 | 激情婷婷在线 | 99久久国产免费看 | 亚洲国产黄色 | 久久久久久久国产精品 | 欧美日韩中文字幕在线视频 | 亚州精品一二三区 | 天天爱天天 | 免费观看午夜视频 | 99热最新网址 | 日韩欧美国产精品 | 91成人网在线播放 | 韩日视频在线 | 一区二区三区精品在线视频 | 国产破处在线视频 | av中文字幕日韩 | 久久a国产 | av免费看电影 | 天天操天天操天天爽 | 日韩中文字幕免费 | 超碰人人射 | 国产在线观看你懂的 | 99亚洲精品| 草在线视频 | 午夜精品久久 | 久久精品视频免费观看 | 一区在线观看 | 久久视频在线免费观看 | 日本精a在线观看 | 国产成人一区在线 | 亚洲精品国偷拍自产在线观看蜜桃 | 色中色亚洲 | 激情亚洲综合在线 | 国产一级免费播放 | 午夜精品久久久久久久久久久 | 色综合久久中文字幕综合网 | 亚洲精品tv久久久久久久久久 | 免费看片在线观看 | 欧美性粗大hdvideo | 五月天堂色 | 日韩免费区 | 亚洲精品国产精品乱码不99热 | 手机av在线免费观看 | 九九热在线精品 | 色妞色视频一区二区三区四区 | 久青草视频在线观看 | 粉嫩av一区二区三区四区在线观看 | 久久精品三 | 国产精品美女免费视频 | 日韩电影在线一区二区 | 久久综合久久久 | 免费av网址大全 | 久久久国产精品人人片99精片欧美一 | 成人a视频片观看免费 | 亚洲自拍偷拍色图 | 亚洲乱码精品 | 国产999精品久久久久久麻豆 | 免费aa大片 | 国产精品久久99精品毛片三a | 综合久久久久久久 | 亚洲五月婷婷 | 国产一线在线 | 国产91av视频在线观看 | 国产91在线播放 | 国产精品久久久 | 很黄很色很污的网站 | 免费国产在线精品 | 亚洲精品99久久久久中文字幕 | 成人理论电影 | 日韩欧美电影在线观看 | 国产vs久久 | 99视频这里有精品 | 精品久久精品久久 | 黄色三级av| 国产高清精品在线观看 | 91精品蜜桃| 欧美久久久久久久久久久久久 | 久久超碰97| 婷婷色资源 | 免费观看视频的网站 | www178ccom视频在线 | 精品av网站 | 国产 在线观看 | 最新国产福利 | 亚洲va欧美va | 91麻豆精品久久久久久 | 欧美日韩精品在线一区二区 | 四虎影视成人永久免费观看视频 | 国产精品黄 | 久久久久亚洲精品成人网小说 | 在线免费观看黄色小说 | 欧美福利久久 | 一级黄色大片 | 毛片基地黄久久久久久天堂 | 成人av免费 | 一级电影免费在线观看 | av在线看片| 91视频久久久久 | 亚洲国产日韩欧美在线 | 国产69精品久久99不卡的观看体验 | 成人免费观看视频大全 | 中文字幕在线观看免费高清电影 | 91片黄在线观看 | 久久欧美精品 | 在线免费观看黄色 | 狠狠干激情| 免费福利视频网站 | 五月天婷亚洲天综合网鲁鲁鲁 | 免费精品国产va自在自线 | 91成人网在线观看 | ww亚洲ww亚在线观看 | 国产免费激情久久 | 日韩电影在线视频 | 欧美巨大荫蒂茸毛毛人妖 | 在线观看网站你懂的 | 成年人视频免费在线播放 | 高清av免费一区中文字幕 | 日韩v欧美v日本v亚洲v国产v | 偷拍精品一区二区三区 | 久草久草在线观看 | 黄色一级免费网站 | 欧美成人在线免费 | 五月天综合在线 | 亚洲欧美在线观看视频 | 国产一级性生活视频 | 美女网站黄免费 | 日本精品视频一区二区 | 欧美视频国产视频 | 青草视频免费观看 | 久久久久久久久久久久久久电影 | 国产精品伦一区二区三区视频 | 精品在线视频一区二区三区 | 91精品黄色 | 亚洲午夜电影网 | 懂色av一区二区在线播放 | 色www永久免费 | 69av视频在线 | 热久精品| 国产麻豆视频网站 | 五月激情姐姐 | av免费高清观看 | 日韩电影在线观看一区 | 精品国产一区二区三区久久影院 | 国产视频999| 91成人精品 | 91av综合| 五月综合激情婷婷 | 欧美一区二区三区四区夜夜大片 | 国产小视频免费在线观看 | 免费在线观看黄网站 | 欧美一级电影在线观看 | 国产成人精品亚洲精品 | 天天玩夜夜操 | 人人爽人人香蕉 | 国产欧美高清 | 久草手机视频 | 亚洲精品一区二区三区在线观看 | 天天爽综合网 | 中文字幕一区二区三区精华液 | 免费看在线看www777 | 亚洲精品国偷自产在线91正片 | 亚欧日韩成人h片 | 91在线色 | 亚洲精品久久久久www | 国产精品久久久久久久久久久久久 | 丁香六月五月婷婷 | 日韩欧美极品 | 高清av在线免费观看 | 欧美精品国产综合久久 | 激情综合五月天 | 99热在| 99草在线视频 | 一区二区电影在线观看 | 日日躁你夜夜躁你av蜜 | 啪啪凸凸 | 九九九电影免费看 | 久久99国产精品久久99 | 国产亚洲精品久久久久久 | 天天操网| 亚洲精品国产精品国 | www最近高清中文国语在线观看 | 在线观看麻豆av | 日韩欧美在线观看 | 亚洲精品伦理在线 | 国产夫妻自拍av | 91人人视频在线观看 | 天天干天天干天天射 | 色婷婷电影 | 日韩视频一区二区在线观看 | 日韩爱爱片 | 中文字幕亚洲欧美日韩 | 成人久久精品视频 | 狠狠狠狠狠色综合 | 久久久久久久免费观看 | 成年人在线观看免费视频 | 欧美一级视频一区 | 中文字幕在线视频一区 | 久久久久久久久久久国产精品 | 免费在线国产视频 | a级片韩国 | 亚洲高清激情 | 精品人人人人 | 日韩在线观看第一页 | 中文字幕一区二区在线播放 | 亚洲欧洲一级 | 欧美一级片播放 | 日本免费一二三区 | 激情av五月婷婷 | 国产精品久久久久久久av电影 | 欧美粗又大 | 亚洲综合在线视频 | 黄色大全视频 | av中文字幕亚洲 | 国产精品日韩在线播放 | 精品国产免费av | av三级在线播放 | 黄色大片免费播放 | 亚洲最新视频在线 | 99久久国产免费免费 | 亚洲女人天堂成人av在线 | www.看片网站 | 国产综合精品一区二区三区 | 国产中文字幕在线免费观看 | 人人干在线观看 | www.狠狠插.com | 人人爽人人爽人人爽 | www.激情五月.com | 日韩高清在线观看 | 中文字幕日韩高清 | 精品久久影院 | 国内视频一区二区 | 激情片av| 免费不卡中文字幕视频 | 国产又黄又硬又爽 | 国产精品av在线 | 国产91全国探花系列在线播放 | 久草在线欧美 | 69亚洲视频 | 亚洲国产日韩欧美 | 免费观看高清 | 中国一 片免费观看 | 98精品国产自产在线观看 | 深爱激情五月综合 | 日韩中文字幕在线 | 亚洲va在线va天堂va偷拍 | 青草视频在线免费 | 91桃花视频 | 国产精品黄网站在线观看 | 精品国产诱惑 | 91精品国产91久久久久福利 | 国产精品视频免费在线观看 | 丁香婷婷在线 | 天堂在线一区二区 | 久久超级碰 | 91在线精品视频 | 六月色婷 | 久久久午夜精品理论片中文字幕 | 久久久久久国产精品免费 | 超碰在97| 精品99久久久久久 | 国产精品美乳一区二区免费 | 亚洲视频,欧洲视频 | 欧美在线a视频 | 成人免费在线电影 | 欧美色图另类 | 精品视频国产 | 五月婷婷久草 | 激情五月视频 | 亚洲作爱视频 | 国产精品成人免费精品自在线观看 | 麻豆精品传媒视频 | 亚洲三区在线 | 欧美在线1 | 91一区二区在线 | 毛片网在线播放 | 国产一区欧美一区 | 成人禁用看黄a在线 | 午夜色影院 | 一区二区三区 亚洲 | 欧美va电影 | 69xx视频 | 中文字幕精品三级久久久 | 亚洲在线视频观看 | 日韩在线观看一区二区三区 | 婷婷色网视频在线播放 | 国产日韩欧美在线一区 | 久久综合色影院 | 国产成人av在线影院 | 欧美激情精品久久久久久 | 欧美永久视频 | 香蕉视频91 | 99午夜| 91在线播 | 91中文字幕网 | 欧美一级片在线免费观看 | av在线中文 | av黄色在线观看 | 成年人在线观看网站 | 天堂av最新网址 | 四虎在线永久免费观看 | 亚洲黄色高清 | 91高清免费在线观看 | 国产人成一区二区三区影院 | 国产一区二区在线观看免费 | 91高清免费在线观看 | 黄色视屏在线免费观看 | 久久精品美女视频网站 | 免费在线观看一区 | 亚洲精品ww | 99视频在线免费播放 | 中文字幕在 | 日韩精品在线观看av | 开心色婷婷 | 中文字幕有码在线观看 | 中文字幕黄色 | 高清av不卡 | 欧美激情视频一二三区 | 亚洲资源 | 91精品久久久久久久久 | 国产一级片不卡 | 最新婷婷色 | 国产视频日韩 | 日韩视频中文字幕在线观看 | 九九色网| 香蕉色综合 | 久久久99精品免费观看app | 国产成人久久av | 偷拍福利视频一区二区三区 | 深爱激情站 | 五月婷婷六月丁香激情 | 中文字幕在线观看91 | 国产精品美女久久久久久久久久久 | 亚洲精品午夜一区人人爽 | 亚洲国产播放 | 日韩免费高清 | 免费激情网 | 在线观看亚洲精品视频 | 成人久久18免费网站图片 | 又爽又黄在线观看 | 国产一区二区三区视频在线 | 91亚洲在线观看 | 成人午夜影院 | 国产中文字幕一区二区三区 | 伊人天天色 | 国产分类视频 | 91av蜜桃 | 国产视频亚洲视频 | 中文字幕精品三级久久久 | 91av网站在线观看 | 在线免费国产 | 国产剧情久久 | 久久草在线视频国产 | 91麻豆精品国产91 | 蜜臀91丨九色丨蝌蚪老版 | 欧美精品国产精品 | 国产精品1区2区在线观看 | 国产一区视频免费在线观看 | a√国产免费a | 免费看一级片 | 中文字幕在线观看一区 | 国产在线观看一 | 美女久久久久久久久久 | 国产美女精品视频 | 日韩成人一级大片 | 97色狠狠| 久久精品中文字幕少妇 | a在线观看国产 | 激情xxxx| 亚洲精品综合在线观看 | 97超级碰碰碰视频在线观看 | 久黄色| 欧美日韩激情视频8区 | 天天干天天怕 | 激情五月婷婷激情 | 成人在线观看影院 | 色综合五月 | 国产成人精品一区二 | 久久久久久国产一区二区三区 | 日本性动态图 | 黄色特一级片 | 久久综合影院 | 国产在线观看h | 黄色在线免费观看网站 | 欧美精品国产综合久久 | av高清网站在线观看 | 国产一区黄色 | 手机看片99 | 98涩涩国产露脸精品国产网 | 国产污视频在线观看 | 在线久久| 麻花豆传媒一二三产区 | 911国产精品 | 国产精品久久久久久久午夜 | 久久国产高清 | 99久久99久久精品国产片 | 免费在线a | 伊人亚洲综合 | 亚洲精品人人 | 伊人久久国产 | 国产精品久久久久久久久搜平片 | 亚洲一区视频在线播放 | 亚洲一区二区黄色 | 亚洲免费一级 | 在线观看国产中文字幕 | 国产精品一区二区在线免费观看 | 国产精品久久久一区二区三区网站 | 亚洲精品久久久久58 | 国产欧美三级 | 日本精品中文字幕 | 国产精品99久久99久久久二8 | 久久亚洲私人国产精品va | 久久免费成人网 | 久久av影视 | 天天干亚洲 | 超碰97国产在线 | 久久视频免费在线 | 国产美女视频黄a视频免费 久久综合九色欧美综合狠狠 | 欧美a级片网站 | 国产资源免费在线观看 | 美女网站在线 | 欧美一二三区在线观看 | 欧美日韩国产区 | 五月婷婷综合色拍 | 久草观看视频 | 国产91免费观看 | 日韩在线观看视频网站 | 亚洲成人精品国产 | 九草在线视频 | 久久视频一区 | 久久午夜鲁丝片 | 日韩爱爱片 | 日本黄色免费电影网站 | 激情五月婷婷网 | 五月色婷 | 人人玩人人添人人澡97 | 久久综合婷婷国产二区高清 | 91精品视频导航 | 中文字幕在线观看完整 | 欧美 日韩 久久 | 97超碰香蕉| 成人av片免费看 | 日本中文字幕在线观看 | 久久歪歪 | 日韩区在线观看 | 91传媒在线观看 | av资源免费在线观看 | aaa亚洲精品一二三区 | 色综合天天综合网国产成人网 | 午夜精品剧场 | 在线天堂亚洲 | 日本三级国产 | 国产视频 亚洲视频 | 日韩av不卡在线播放 | 91理论片午午伦夜理片久久 | 不卡的av在线播放 | 少妇性bbb搡bbb爽爽爽欧美 | 一区二区三区四区在线 | 操综合| 天天干,夜夜爽 | 国产成人精品一区二区三区免费 | 天天干国产 | 一区二区三区不卡在线 | 精品久久一二三区 | 一区在线播放 | 成年免费在线视频 | 视频二区在线视频 | 中文字幕欧美日韩va免费视频 | 亚洲激色 | 日韩毛片精品 | 国产四虎影院 | 国内免费久久久久久久久久久 | 久久综合五月婷婷 | 麻豆91网站| 天天做天天爱天天爽综合网 | 久久视频在线 | av在线最新 | 成年人在线免费看片 | 激情五月激情综合网 | 国产丝袜高跟 | 日韩毛片久久久 | 免费久久片 | 91视频久久久 | 日日干激情五月 | 麻豆视频免费在线 | 婷婷中文字幕 | 国产精品欧美一区二区 | www.啪啪.com | 西西人体4444www高清视频 | 91久久精品日日躁夜夜躁国产 | 国产精品一区二区三区免费视频 | 国产涩涩在线观看 | 欧美一级片免费 | 日韩黄色在线 | 91在线中字 | 99精品亚洲| 五月婷婷六月丁香 | 日韩av专区 | 国产精品wwwwww | 亚洲天堂网在线观看视频 | 欧美最猛性xxxx | 亚洲精品国产精品国产 | 激情综合电影网 | 91粉色视频 | 日日精品 | 免费在线国产精品 | 国产精品孕妇 | 久草在线资源网 | 久久人人爽人人人人片 | 成人午夜电影在线 | 久久激情五月激情 | 91亚洲精品久久久蜜桃网站 | 亚洲视频 在线观看 | 九九久久久久久久久激情 | 一性一交视频 | 免费看的av片 | 91欧美日韩国产 | 久久综合色影院 | 欧美一区免费观看 | 黄色软件视频大全免费下载 | 国产精品色在线 | 精品久久五月天 | 不卡的av在线 | 手机在线看永久av片免费 | 韩国一区二区av | 亚洲精品456在线播放第一页 | av+在线播放在线播放 | 91手机电影 | www.日本色| 亚洲国产高清在线观看视频 | 亚洲精品高清在线观看 | 亚洲乱码在线观看 | 日韩大陆欧美高清视频区 | 肉色欧美久久久久久久免费看 | 中文字幕国语官网在线视频 | 99热高清 | 五月婷亚洲 | 最近中文字幕在线播放 | 在线v片| 欧美日韩免费观看一区二区三区 | 麻豆精品视频在线 | 国产午夜精品福利视频 | 91成人网在线观看 | 国产又粗又猛又爽又黄的视频免费 | 日韩精品不卡在线 | 国产中文字幕在线看 | av福利网址导航大全 | 国产精品九九视频 | 九九九九精品九九九九 | av一级片 | 久久久久亚洲精品成人网小说 | 国产亚洲精品久久久网站好莱 | 久久精品79国产精品 | 日本论理电影 | 欧美xxxx性xxxxx高清 | 国产精品一区二区三区在线免费观看 | 二区视频在线 | 99爱这里只有精品 | 日本精品一区二区在线观看 | 国产一区高清在线观看 | av在线等 | 午夜影院一级 | 日韩一区二区三区在线观看 | 国产一级片播放 | 国产在线视频资源 | av网站有哪些 | 国产亚洲一区二区在线观看 | 黄色网在线播放 | 久久黄色免费视频 | 97视频精品| 在线看片a | 久草免费在线观看视频 | 日日色综合 | 中文字幕在线观看免费高清完整版 | 亚洲高清在线 | 国产色妞影院wwwxxx | 91色亚洲 | 69国产精品视频免费观看 | 亚洲激情五月 | 精品视频免费看 | 天天狠狠 | 免费韩国av| 久久国产精品99久久久久 | 国产成人一区二区啪在线观看 | 免费在线播放视频 | 国产色黄网站 | 天天摸天天操天天舔 | 草久久久 | 在线亚洲观看 | 成人小视频在线观看免费 | 免费看特级毛片 | 国产亚洲精品电影 | 91久久国产自产拍夜夜嗨 | 精品国产91亚洲一区二区三区www | 国产精品99久久久久久久久久久久 | 中文字幕观看在线 | 一区二区三区精品久久久 | 五月婷婷六月丁香在线观看 | 亚洲日本三级 | 欧美成人按摩 | 国产精品美女久久久久久网站 | 欧美va在线观看 | 中文字幕一区二区三区在线播放 | 欧美日韩免费网站 | 91九色精品国产 | 懂色av懂色av粉嫩av分享吧 | 国产在线毛片 | 久久久久国产一区二区三区 | 国产盗摄精品一区二区 | 亚洲精品xx| 玖草在线观看 | 亚洲黄色免费电影 | 日本精品一区二区三区在线播放视频 | 天天干天天操天天操 | 超碰97免费观看 | 不卡av电影在线 | 色久av| 国产原创在线视频 | 午夜视频99 | 一区二区不卡视频在线观看 | 午夜国产在线 | 在线观看av中文字幕 | 日本精品视频免费观看 | 波多野结衣视频在线 | 欧美日韩高清 | 日韩一级黄色大片 | 一本一道久久a久久综合蜜桃 | 午夜影视一区 | 久久久久综合网 | 在线视频中文字幕一区 | 综合网天天色 | 久久精品美女视频网站 | 日韩欧美高清一区二区 | 国产视频91在线 | 狠狠色丁香久久婷婷综合丁香 | 99热在线看 | 99久久夜色精品国产亚洲 | 亚洲精品久久在线 | 成人国产精品免费观看 | 96国产精品视频 | a'aaa级片在线观看 | 国产又粗又猛又黄 | 99自拍视频在线观看 | 99在线视频网站 | 欧美午夜精品久久久久久孕妇 | 黄网站免费大全入口 | 日批网站免费观看 | 免费观看v片在线观看 | 99产精品成人啪免费网站 | 国产96在线视频 | 日韩激情中文字幕 | www.久久色 | 丁香婷婷激情啪啪 | 天天操天 | 亚洲黄色av | 国产.精品.日韩.另类.中文.在线.播放 | 亚洲精品久久久久久久蜜桃 | 久久视频精品在线观看 | 婷婷黄色片| 日韩精品一区二区在线视频 | av免费福利 | 久久精品美女视频网站 | 91激情视频在线 | 日韩中字在线 | 久草网站在线观看 | 久久亚洲热 | 色婷婷综合久久久久中文字幕1 | 国产精品国产自产拍高清av | 免费黄色a网站 | 日韩中文在线电影 | 91中文视频 | 国产麻豆精品久久 | 亚洲精品美女在线观看 | 波多野结衣电影一区二区三区 | www.超碰| 欧美一区二区免费在线观看 | 91精品啪在线观看国产81旧版 | 国产乱老熟视频网88av | 一区二区三区四区不卡 | 99久久精品午夜一区二区小说 | 九色在线视频 | 久久丁香 | 91视频免费看网站 | 欧美一级小视频 | 久久免费在线视频 | 国产精品久久久久免费观看 | 韩国av免费观看 | 国产在线视频导航 | 国产一区二区三精品久久久无广告 | 99久久婷婷国产综合精品 | 99色婷婷 | 国产在线第三页 | 国产一级免费电影 | 97超级碰碰碰视频在线观看 | 久久99爱视频 | 在线91播放| 成人黄色小说在线观看 | 中文字幕黄色网址 | 九九免费精品视频在线观看 | av在线一二三区 | 狠狠干 狠狠操 | 成人精品国产 | 日本久草电影 | 亚洲天天在线日亚洲洲精 | 亚洲国产中文字幕在线观看 | 亚洲精品福利在线观看 | 91精品办公室少妇高潮对白 | 一区二区三区四区五区六区 | 天海冀一区二区三区 | 成人av手机在线 | 久久亚洲影院 | 久久亚洲精品国产亚洲老地址 | 精品久久久久一区二区国产 | 99日精品| 97干com | 国产又粗又猛又黄又爽 | 国产精品原创在线 | 日韩理论 | 久久免费精品国产 | 黄色一级免费网站 | 国产性天天综合网 | 国产精品高潮久久av | 黄色小说免费观看 | 久久综合狠狠综合久久综合88 | av中文字幕网站 | 国产免费资源 | www九九热 | 欧美在线视频一区二区三区 | 国产在线观看av | 国产精品无av码在线观看 | 依人成人综合网 | 久久久午夜视频 | 在线最新av | 国产69精品久久久久久 | 在线观看亚洲免费视频 | 亚洲一区尤物 | 国产91在线免费视频 | 午夜精品电影一区二区在线 | 中国一级片在线 | 99视频在线看 | 91高清一区 | 欧美色图亚洲图片 | 亚洲一区久久 | 福利一区二区三区四区 | 97超碰超碰久久福利超碰 | 亚洲精品乱码久久久久久 | 精品国产成人在线影院 | 亚洲狠狠婷婷综合久久久 | 国产午夜一区二区 | 国产成本人视频在线观看 | 亚洲精品在线电影 | 久久69av | 日韩在线视频观看 | 色综合久久88色综合天天人守婷 | 久久视频一区二区 | 午夜视频在线观看一区 | 日韩欧美xxx | 免费黄色a网站 | 狠狠色婷婷丁香六月 | 日韩理论片中文字幕 | 日韩激情片在线观看 | 国产日韩三级 | 国产高清免费观看 | 色激情在线| 69国产盗摄一区二区三区五区 | 亚洲国产日韩一区 | 日韩福利在线观看 | 99精品久久只有精品 | 最近中文字幕完整高清 | 麻豆久久一区二区 | 日韩在线观看影院 | 2020天天干夜夜爽 | 麻豆视频免费观看 | 国产黄色片免费观看 | 成年人网站免费观看 | 免费a v在线 | 久久黄色小说视频 | 亚洲精品国 | 日本久久久久 | 久久综合免费视频 | 美女av免费看 | 日韩精品网址 | 欧美日一级片 | 亚洲精品黄色在线观看 | 美女黄频网站 | 久久99九九99精品 | 偷拍福利视频一区二区三区 | 亚洲激情六月 | 国产91大片 | 欧美在线你懂的 | 91大神在线观看视频 | 亚洲国产精品500在线观看 | 最近高清中文在线字幕在线观看 | 日韩av男人的天堂 | 超碰免费在线公开 | 久久黄色影院 | 国产又黄又猛又粗 | 成人黄色大片在线免费观看 | 天天射天天做 | 一级片视频在线 | 国产午夜影院 | 国产成人一区二区三区久久精品 | 精品天堂av| 999热线在线观看 | 99精品欧美一区二区 | 免费三级黄色 | 干综合网 | v片在线看 | 久久久www免费电影网 | 日韩精品一区二区三区高清免费 | 三级黄色免费片 | 麻花豆传媒一二三产区 | 日韩视频在线一区 | 亚洲三级黄色 | 色全色在线资源网 | 久久精品一区八戒影视 | 中文字幕有码在线播放 | 五月婷婷欧美视频 | 亚洲精品视频大全 | 久久久91精品国产一区二区三区 | 日韩电影中文,亚洲精品乱码 | 黄色一级免费网站 | 激情久久综合 | 狠狠五月婷婷 | 国产精品久久久久久久久久久免费 | 99热九九这里只有精品10 | 韩国av免费观看 | 91香蕉视频 | 成人丁香花 | 在线观看视频精品 | 久久久久五月天 | 五月综合 | 高清精品在线 | 国产 一区二区三区 在线 | 国产福利免费在线观看 | 日韩精品免费在线观看视频 | 日韩女同一区二区三区在线观看 | 日韩欧美视频免费看 | 韩国一区二区三区在线观看 | 国产色婷婷在线 | 国产精品成人免费精品自在线观看 | 一级片黄色片网站 | 国产小视频精品 | 中文高清av| 韩国精品福利一区二区三区 | 69国产精品视频 | 日韩一二区在线观看 | 欧美一区二区三区激情视频 | 久久超碰97 | 日韩视频一区二区 | 夜夜视频资源 | 国产成人久久精品亚洲 | 在线观看国产高清视频 | 亚洲涩涩网站 | 日本少妇高清做爰视频 | 2019天天干天天色 | 中文字幕在线视频一区 | 91麻豆免费视频 | 国产精品美女久久久久久久久 | av电影免费看 | 色偷偷网站视频 | 久久99国产精品免费网站 | 久久综合色天天久久综合图片 | 狠狠色噜噜狠狠狠 | av中文字幕亚洲 | 曰本免费av | 久久精品高清视频 | 久久影视网| 视频一区在线免费观看 | 免费在线观看视频a | 99精品一级欧美片免费播放 | 国产精品精品国产婷婷这里av | 在线免费观看黄色av | 深爱激情久久 | 欧美国产日韩激情 | 黄色毛片一级片 | 成人va视频| 亚洲精品在线观看视频 | 久久婷综合 | 久久久久亚洲精品男人的天堂 | 奇米导航 | 欧美一级电影片 | 天天激情站 | 成 人 黄 色 免费播放 | 国产精品美女久久久久久久久 | 9在线观看免费高清完整版在线观看明 | 欧美在线观看小视频 | 久久草精品| 中文字幕精品在线 | 在线免费中文字幕 | 国产成人精品亚洲日本在线观看 | 91av在线看| 天天干天天摸天天操 | www在线观看视频 | 久久免费国产精品1 | 中文免费在线观看 | 亚洲第一区精品 | 在线亚洲人成电影网站色www | 天天射射天天 | 亚洲精品高清视频 | 亚洲一区久久久 | 久久女同性恋中文字幕 | 日韩在线免费高清视频 | 中文字幕高清有码 | 久久免费中文视频 | 久久不卡视频 | 久久99亚洲精品 | 中文字幕精品一区二区三区电影 | 欧美在一区| 91一区一区三区 | 在线视频观看成人 | 国产午夜精品理论片在线 | 国产精品理论片在线播放 | 国产一区二区网址 | 91丨九色丨高潮丰满 | 欧美国产日韩久久 | 国产精品第72页 | 久精品视频在线 | 成年人黄色av | 免费网站观看www在线观看 | 久久久久久久久久久电影 | 亚洲第一区在线播放 | 国产精品一区专区欧美日韩 | 天天干天天摸天天操 | 综合激情 | 蜜臀av夜夜澡人人爽人人桃色 | 丝袜美腿av | 99精品久久99久久久久 | 99在线精品视频观看 | 久久dvd| 91经典在线 | 成人免费一级 | 91精品久久久久久久91蜜桃 | 免费看成人av | 久久人人爽 | 色综合久久五月 | 久久综合桃花 | 天天天色综合a | 日韩欧美精品在线观看视频 | 天天操天天操一操 | 成人羞羞视频在线观看免费 | av成人黄色 | 亚洲国产大片 | 国产精品麻豆果冻传媒在线播放 | 日韩免费在线网站 | 久久爱www.| 超碰97公开| 日韩视频www| 国产在线观看91 | 亚洲闷骚少妇在线观看网站 | 国产亚洲精品成人av久久ww | 久久久久久久国产精品影院 | 在线观看黄色大片 |