Alibaba-Dexposed Bug框架原理及源码解析


目录(?)
[+]

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

上一篇中已经介绍了Alibaba-Dexposed框架在线热补丁修复的使用 ,这篇主要是了解框架的原理和源码解析。

这里写图片描述

原理:

在Dalvik虚拟机下,主要是通过改变一个方法对象方法在Dalvik虚拟机中的定义来实现,具体做法就是将该方法的类型改变为Native并且将这个方法的实现链接到一个通用的Native Dispatch方法上。这个 Dispatch方法通过JNI回调到Java端的一个统一处理方法,最后在统一处理方法中调用before, after函数来实现AOP。在Art虚拟机上目前也是通过改变一个 ArtMethod的入口函数来实现。

在宿主项目的Application需要调用以下方法来判断手机是否支持Dexposed框架:

<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;">DexposedBridge.canDexposed(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">this</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>

canDexposed方法源码:

<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;">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;">canDexposed</span>(Context context) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> !DeviceCheck.isDeviceSupport(context)?<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>:loadDexposedLib(context);
    }</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></ul>

可以看到,第一判断了机型是否支持,如果支持就加载lib文件。 
DeviceCheck.isDeviceSupport()源码:

<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;">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;">isDeviceSupport</span>(Context context) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">boolean</span> var2;
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span>(!isCheckedDeviceSupport) {
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span>(isDalvikMode() && isSupportSDKVersion() && !isX86CPU() && !isYunOS()) {
                    isDeviceSupportable = <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> isDeviceSupportable;
                }

                isDeviceSupportable = <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> isDeviceSupportable;
            }

            var2 = isDeviceSupportable;
        } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">finally</span> {
            Log.d(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"hotpatch"</span>, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"device support is "</span> + isDeviceSupportable + <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"checked"</span> + isCheckedDeviceSupport);
            isCheckedDeviceSupport = <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> var2;
    }</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></ul>

判断机型,主要判断的有是否是Dalvik虚拟机、sdk版本、是否是x86cpu架构、是否是YunOS系统。

loadDexposedLib加载lib的源码:

<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;">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;">loadDexposedLib</span>(Context context) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span>(VERSION.SDK_INT != <span class="hljs-number" style="color:#06666;box-sizing: border-box;">10</span> && VERSION.SDK_INT != <span class="hljs-number" style="color:#06666;box-sizing: border-box;">9</span>) {
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span>(VERSION.SDK_INT > <span class="hljs-number" style="color:#06666;box-sizing: border-box;">19</span>) {
                    System.loadLibrary(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"dexposed_l"</span>);
                } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {
                    System.loadLibrary(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"dexposed"</span>);
                }
            } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {
                System.loadLibrary(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"dexposed2.3"</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;">catch</span> (Throwable var2) {
            <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>;
        }
    }</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></ul>

根据sdk的不同版本加载不同的so文件。

以上仅是判断当然机型是否支持Dexposed框架的运行环境。

接下,就是对Dexposed的使用原理进行源码分析:

在上一篇提到,当加载补丁文件时,会扫描补丁文件中实现IPatch接口的所有的类。 
IPatch定义如下:

<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;">interface</span> IPatch {
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> handlePatch(PatchParam var1) throws Throwable;
}</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></ul>

就是说,修复bug的处理只能在handlePatch方法中实现。

官网也只提供了2种实现方式: 
第一:

<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-comment" style="color:#8800;box-sizing: border-box;">// Target class, method with parameter types, followed by the hook callback (XC_MethodHook).</span>
        DexposedBridge.findAndHookMethod(Activity.class, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"onCreate"</span>, Bundle.class, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> XC_MethodHook() {

            <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// To be invoked before Activity.onCreate().</span>
            <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> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">beforeHookedMethod</span>(MethodHookParam param) <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> Throwable {
                <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// "thisObject" keeps the reference to the instance of target class.</span>
                Activity instance = (Activity) param.thisObject;

                <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// The array args include all the parameters.</span>
                Bundle bundle = (Bundle) param.args[<span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>];
                Intent intent = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> Intent();
                <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// XposedHelpers provide useful utility methods.</span>
                XposedHelpers.setObjectField(param.thisObject, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"mIntent"</span>, intent);

                <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Calling setResult() will bypass the original method body use the result as method return value directly.</span>
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (bundle.containsKey(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"return"</span>))
                    param.setResult(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>);
            }

            <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// To be invoked after Activity.onCreate()</span>
            <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> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">afterHookedMethod</span>(MethodHookParam param) <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throws</span> Throwable {
                XposedHelpers.callMethod(param.thisObject, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"sampleMethod"</span>, <span class="hljs-number" style="color:#06666;box-sizing: border-box;">2</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><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li></ul>

第二:

<code class="hljs r 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;"> DexposedBridge.findAndHookMethod(Activity.class, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"onCreate"</span>, Bundle.class, new XC_MethodReplacement() {

            @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                // Re-writing the method logic outside the original method context is a bit tricky but still viable.
                <span class="hljs-keyword" style="color:#0088;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><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></ul>

调用的接口是相同的,只不过传递的回调接口不同。 
第一种是在方法前后执行做一些处理,第二种就是直接把方法进行替换。

在这里,我们就重点看findAndHookMethod方法,跟着此方法追踪源码:

<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;">static</span> Unhook <span class="hljs-title" style="box-sizing: border-box;">findAndHookMethod</span>(Class<?> clazz, String methodName, Object... parameterTypesAndCallback) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span>(parameterTypesAndCallback.length != <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span> && parameterTypesAndCallback[parameterTypesAndCallback.length - <span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>] <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">instanceof</span> XC_MethodHook) {
            XC_MethodHook callback = (XC_MethodHook)parameterTypesAndCallback[parameterTypesAndCallback.length - <span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>];
            Method m = XposedHelpers.findMethodExact(clazz, methodName, parameterTypesAndCallback);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//根据Java的反射机制获取到Method对象</span>
            Unhook unhook = hookMethod(m, callback);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//见下方代码分析</span>
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span>(!(callback <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">instanceof</span> XC_MethodKeepHook) && !(callback <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">instanceof</span> XC_MethodKeepReplacement)) {
                ArrayList var6 = allUnhookCallbacks;
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">synchronized</span>(allUnhookCallbacks) {
                    allUnhookCallbacks.add(unhook);
                }
            }

            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> unhook;
        } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</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> IllegalArgumentException(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"no callback defined"</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></ul>

hookMethod方法源码:

<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;">static</span> Unhook <span class="hljs-title" style="box-sizing: border-box;">hookMethod</span>(Member hookMethod, XC_MethodHook callback) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span>(!(hookMethod <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">instanceof</span> Method) && !(hookMethod <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">instanceof</span> Constructor)) {
            <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> IllegalArgumentException(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"only methods and constructors can be hooked"</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;">boolean</span> newMethod = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;
            Map declaringClass = hookedMethodCallbacks;
            DexposedBridge.CopyOnWriteSortedSet callbacks;
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">synchronized</span>(hookedMethodCallbacks) {
                callbacks = (DexposedBridge.CopyOnWriteSortedSet)hookedMethodCallbacks.get(hookMethod);
                <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//如果没有修复此方法,就创建一个回调接口的集合</span>
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span>(callbacks == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>) {
                    callbacks = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> DexposedBridge.CopyOnWriteSortedSet();
                    hookedMethodCallbacks.put(hookMethod, callbacks);
                    newMethod = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">true</span>;
                }
            }

            callbacks.add(callback);
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span>(newMethod) {<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//如果是新方法,获取方法的参数列表和返回值</span>
                Class declaringClass1 = hookMethod.getDeclaringClass();
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> slot = runtime == <span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>?XposedHelpers.getIntField(hookMethod, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"slot"</span>):<span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>;
                Class[] parameterTypes;
                Class returnType;
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span>(hookMethod <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">instanceof</span> Method) {
                    parameterTypes = ((Method)hookMethod).getParameterTypes();
                    returnType = ((Method)hookMethod).getReturnType();
                } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {
                    parameterTypes = ((Constructor)hookMethod).getParameterTypes();
                    returnType = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>;
                }

                DexposedBridge.AdditionalHookInfo additionalInfo = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> DexposedBridge.AdditionalHookInfo(callbacks, parameterTypes, returnType, (DexposedBridge.AdditionalHookInfo)<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>);
                <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//调用Native方法,接口在下方</span>
                hookMethodNative(hookMethod, declaringClass1, slot, additionalInfo);
            }

            callback.getClass();
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> Unhook(callback, hookMethod);<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//返回一个Unhook实例对象</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><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></ul>

hookMethodNative Native方法生命:

<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;">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;">synchronized</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;">hookMethodNative</span>(Member var0, Class<?> var1, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> var2, Object var3);</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>

Dalvik虚拟机的Native方法实现:

hookMethodNative Native层的代码实现:

<code class="hljs oxygene 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;">static</span> void com_taobao_android_dexposed_DexposedBridge_hookMethodNative(JNIEnv* env, jclass clazz, jobject reflectedMethodIndirect,
            jobject declaredClassIndirect, jint slot, jobject additionalInfoIndirect) <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">{s
    // Usage errors?
    if (declaredClassIndirect == NULL || reflectedMethodIndirect == NULL) {
        dvmThrowIllegalArgumentException("method and declaredClass must not be null");
        return;
    }</span>

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Find the internal representation of the method</span>
    ClassObject* declaredClass = (ClassObject*) dvmDecodeIndirectRef(dvmThreadSelf(), declaredClassIndirect);
    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">Method</span>* <span class="hljs-title" style="box-sizing: border-box;">method</span> = <span class="hljs-title" style="box-sizing: border-box;">dvmSlotToMethod</span><span class="hljs-params" style="color:#66066;box-sizing: border-box;">(declaredClass, slot)</span>;</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把Java的Method映射为Native Method</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">method</span> == <span class="hljs-title" style="box-sizing: border-box;">NULL</span>) <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">{
        dvmThrowNoSuchMethodError("could not get internal representation for method");
        return;
    }</span>

    <span class="hljs-title" style="box-sizing: border-box;">if</span> <span class="hljs-params" style="color:#66066;box-sizing: border-box;">(dexposedIsHooked(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">method</span>)</span>) <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">{//判断此方法是否已经被hook(钩)
        // already hooked
        return;
    }</span>

    // <span class="hljs-title" style="box-sizing: border-box;">Save</span> <span class="hljs-title" style="box-sizing: border-box;">a</span> <span class="hljs-title" style="box-sizing: border-box;">copy</span> <span class="hljs-title" style="box-sizing: border-box;">of</span> <span class="hljs-title" style="box-sizing: border-box;">the</span> <span class="hljs-title" style="box-sizing: border-box;">original</span> <span class="hljs-title" style="box-sizing: border-box;">method</span> <span class="hljs-title" style="box-sizing: border-box;">and</span> <span class="hljs-title" style="box-sizing: border-box;">other</span> <span class="hljs-title" style="box-sizing: border-box;">hook</span> <span class="hljs-title" style="box-sizing: border-box;">info</span>
    <span class="hljs-title" style="box-sizing: border-box;">DexposedHookInfo</span>* <span class="hljs-title" style="box-sizing: border-box;">hookInfo</span> = <span class="hljs-params" style="color:#66066;box-sizing: border-box;">(DexposedHookInfo*)</span> <span class="hljs-title" style="box-sizing: border-box;">calloc</span><span class="hljs-params" style="color:#66066;box-sizing: border-box;">(1, sizeof(DexposedHookInfo)</span>);</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//新申请一块内存</span>
    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//备份method对象到hookInfo中</span>
    memcpy(hookInfo, <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">method</span>, <span class="hljs-title" style="box-sizing: border-box;">sizeof</span><span class="hljs-params" style="color:#66066;box-sizing: border-box;">(hookInfo->originalMethodStruct)</span>);</span>
    hookInfo->reflectedMethod = dvmDecodeIndirectRef(dvmThreadSelf(), env->NewGlobalRef(reflectedMethodIndirect));<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把方法的实现指向native方法的实现,指针替换</span>
    hookInfo->additionalInfo = dvmDecodeIndirectRef(dvmThreadSelf(), env->NewGlobalRef(additionalInfoIndirect));

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Replace method with our own code</span>
    SET_METHOD_FLAG(<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">method</span>, <span class="hljs-title" style="box-sizing: border-box;">ACC_NATIVE</span>);</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把method对象方法属性设置成native方法</span>

    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">method</span>-><span class="hljs-title" style="box-sizing: border-box;">insns</span> = <span class="hljs-params" style="color:#66066;box-sizing: border-box;">(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">const</span> u2*)</span> <span class="hljs-title" style="box-sizing: border-box;">hookInfo</span>;</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//把备份的method数据挂在这里传递数据</span>
    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">method</span>-><span class="hljs-title" style="box-sizing: border-box;">registersSize</span> = <span class="hljs-title" style="box-sizing: border-box;">method</span>-><span class="hljs-title" style="box-sizing: border-box;">insSize</span>;</span>
    <span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">method</span>-><span class="hljs-title" style="box-sizing: border-box;">outsSize</span> = 0;</span>

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (PTR_gDvmJit != NULL) <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">{
        // reset JIT cache
        MEMBER_VAL(PTR_gDvmJit, DvmJitGlobals, codeCacheFull) = true;
    }</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><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></ul>
<code class="hljs oxygene 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-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">method</span>-><span class="hljs-title" style="box-sizing: border-box;">nativeFunc</span> = &<span class="hljs-title" style="box-sizing: border-box;">dexposedCallHandler</span>;</span><span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//链接到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></ul>

当虚拟机调用到这个存在bug的方法时就会调用这个Native方法: 
dexposedCallHandler方法源码:

<code class="hljs objectivec 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;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> dexposedCallHandler(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">const</span> u4* args, JValue* pResult, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">const</span> Method* method, ::Thread* <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">self</span>) {

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!dexposedIsHooked(method)) {
        dvmThrowNoSuchMethodError(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"could not find Dexposed original method - how did you even get here?"</span>);
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;
    }

    DexposedHookInfo* hookInfo = (DexposedHookInfo*) method->insns;
    Method* original = (Method*) hookInfo;
    Object* originalReflected = hookInfo->reflectedMethod;
    Object* additionalInfo = hookInfo->additionalInfo;

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// convert/box arguments</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">char</span>* desc = &method->shorty[<span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>]; <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// [0] is the return type.</span>
    Object* thisObject = <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">NULL</span>;
    size_t srcIndex = <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>;
    size_t dstIndex = <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>;

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// for non-static methods determine the "this" pointer</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!dvmIsStaticMethod(original)) {
        thisObject = (Object*) args[<span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>];
        srcIndex++;
    }

    ArrayObject* argsArray = dvmAllocArrayByClass(objectArrayClass, strlen(method->shorty) - <span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>, ALLOC_DEFAULT);
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (argsArray == <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">NULL</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;">while</span> (*desc != <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'\0'</span>) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">char</span> descChar = *(desc++);
        JValue value;
        Object* obj;

        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">switch</span> (descChar) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">case</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'Z'</span>:
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">case</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'C'</span>:
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">case</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'F'</span>:
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">case</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'B'</span>:
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">case</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'S'</span>:
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">case</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'I'</span>:
            value<span class="hljs-variable" style="color:#66066;box-sizing: border-box;">.i</span> = args[srcIndex++];
            obj = (Object*) dvmBoxPrimitive(value, dvmFindPrimitiveClass(descChar));
            dvmReleaseTrackedAlloc(obj, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">self</span>);
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">break</span>;
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">case</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'D'</span>:
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">case</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'J'</span>:
            value<span class="hljs-variable" style="color:#66066;box-sizing: border-box;">.j</span> = dvmGetArgLong(args, srcIndex);
            srcIndex += <span class="hljs-number" style="color:#06666;box-sizing: border-box;">2</span>;
            obj = (Object*) dvmBoxPrimitive(value, dvmFindPrimitiveClass(descChar));
            dvmReleaseTrackedAlloc(obj, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">self</span>);
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">break</span>;
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">case</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'['</span>:
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">case</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">'L'</span>:
            obj  = (Object*) args[srcIndex++];
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">break</span>;
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">default</span>:
            ALOGE(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Unknown method signature description character: %c\n"</span>, descChar);
            obj = <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">NULL</span>;
            srcIndex++;
        }
        dexposedSetObjectArrayElement(argsArray, dstIndex++, obj);
    }

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// call the Java handler function</span>
    JValue result;
    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//调用了Java层的方法</span>
    dvmCallMethod(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">self</span>, dexposedHandleHookedMethod, <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">NULL</span>, &result,
        originalReflected, (<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span>) original, additionalInfo, thisObject, argsArray);

    dvmReleaseTrackedAlloc((Object *)argsArray, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">self</span>);

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// exceptions are thrown to the caller</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (dvmCheckException(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">self</span>)) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;
    }

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// return result with proper type</span>
    ClassObject* returnType = dvmGetBoxedReturnType(method);
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (returnType->primitiveType == PRIM_VOID) {
        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// ignored</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> (result<span class="hljs-variable" style="color:#66066;box-sizing: border-box;">.l</span> == <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">NULL</span>) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (dvmIsPrimitiveClass(returnType)) {
            dvmThrowNullPointerException(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"null result when primitive expected"</span>);
        }
        pResult->l = <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">NULL</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> (!dvmUnboxPrimitive((Object *)result<span class="hljs-variable" style="color:#66066;box-sizing: border-box;">.l</span>, returnType, pResult)) {
            dvmThrowClassCastException(((Object *)result<span class="hljs-variable" style="color:#66066;box-sizing: border-box;">.l</span>)->clazz, returnType);

        }
    }
}</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></ul>

这个方法主要就是调用Java的方法,实现调度。 
调用的Java的方法是:

<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;">private</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">static</span> Object <span class="hljs-title" style="box-sizing: border-box;">handleHookedMethod</span>(Member method, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> originalMethodId, Object additionalInfoObj,
            Object thisObject, Object[] args) throws Throwable {
        AdditionalHookInfo additionalInfo = (AdditionalHookInfo) additionalInfoObj;

        Object[] callbacksSnapshot = additionalInfo.callbacks.getSnapshot();
        final <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> callbacksLength = callbacksSnapshot.length;
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (callbacksLength == <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</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;">return</span> invokeOriginalMethodNative(method, originalMethodId, additionalInfo.parameterTypes,
                        additionalInfo.returnType, thisObject, args);
            } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (InvocationTargetException e) {
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throw</span> e.getCause();
            }
        }

        MethodHookParam param = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">new</span> MethodHookParam();
        param.method  = method;
        param.thisObject = thisObject;
        param.args = args;

        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// call "before method" callbacks</span>
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> beforeIdx = <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>;
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">do</span> {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {
                ((XC_MethodHook) callbacksSnapshot[beforeIdx]).beforeHookedMethod(param);
            } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (Throwable t) {
                log(t);

                <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// reset result (ignoring what the unexpectedly exiting callback did)</span>
                param.setResult(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>);
                param.returnEarly = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">continue</span>;
            }

            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (param.returnEarly) {
                <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// skip remaining "before" callbacks and corresponding "after" callbacks</span>
                beforeIdx++;
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">break</span>;
            }
        } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">while</span> (++beforeIdx < callbacksLength);

        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// call original method if not requested otherwise</span>
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!param.returnEarly) {
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {
                param.setResult(invokeOriginalMethodNative(method, originalMethodId,
                        additionalInfo.parameterTypes, additionalInfo.returnType, param.thisObject, param.args));
            } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (InvocationTargetException e) {
                param.setThrowable(e.getCause());
            }
        }

        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// call "after method" callbacks</span>
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> afterIdx = beforeIdx - <span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>;
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">do</span> {
            Object lastResult =  param.getResult();
            Throwable lastThrowable = param.getThrowable();

            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">try</span> {
                ((XC_MethodHook) callbacksSnapshot[afterIdx]).afterHookedMethod(param);
            } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">catch</span> (Throwable t) {
                DexposedBridge.log(t);

                <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// reset to last result (ignoring what the unexpectedly exiting callback did)</span>
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (lastThrowable == <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">null</span>)
                    param.setResult(lastResult);
                <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span>
                    param.setThrowable(lastThrowable);
            }
        } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">while</span> (--afterIdx >= <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>);

        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// return</span>
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (param.hasThrowable())
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">throw</span> param.getThrowable();
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span>
            <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> param.getResult();
    }</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></ul>

这个方法里面了实现了调度机制,调用回调接口的方法和备份的Java方法。 
本质上仍然是寻找被挂钩函数的 Method 结构体,将Method属性改为native ,然后对其成员 nativeFunc, 
registersize 等进行赋值,其中 insns 成员保存了挂钩的详细信息。所有被挂钩的函数,其nativeFunc都赋值为 dexposedCallHandler 函数,该函数最终执行 XposedBridge.class 里的 handleHookedMethod 。 handleHookedMethod 寻找dexposed模块及dexposed框架调用 findAndHookMethod 注册的 before,after 
函数,如果有,就执行,再通过invokeOriginalMethodNative 执行挂钩前函数。

MethodHookParam.thisObject:这个类的一个实例 
MethodHookParam.args:用于传递被注入函数的所有参数 
MethodHookParam.setResult:用于修改原函数调用的结果,如果在beforeHookedMethod回调函数中调用setResult,可以阻止对原函数的调用。但是如果有返回值的话仍然需要通过hook处理器进行return操作。

Art虚拟机的Native方法实现

<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;">static <span class="hljs-literal" style="color:#06666;box-sizing: border-box;">void</span> com_taobao_android_dexposed_DexposedBridge_hookMethodNative(
            JNIEnv<span class="hljs-subst" style="color:#000000;box-sizing: border-box;">*</span> env, jclass, jobject java_method, jobject, jint,
            jobject additional_info) {

        ScopedObjectAccess soa(env);
        art<span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::Thread</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;">self</span> <span class="hljs-subst" style="color:#000000;box-sizing: border-box;">=</span> art<span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::Thread</span><span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::Current</span>();

        jobject javaArtMethod <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>GetObjectField(java_method,
                WellKnownClasses<span class="hljs-tag" style="color:#06666;box-sizing: border-box;">::java_lang_reflect_AbstractMethod_artMethod</span>);
        ArtMethod<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> soa<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">.</span>Decode<span class="hljs-subst" style="color:#000000;box-sizing: border-box;"><</span>mirror<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>(javaArtMethod);

        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">LOG</span>(INFO) <span class="hljs-subst" style="color:#000000;box-sizing: border-box;"><<</span> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"dexposed: >>> hookMethodNative "</span> <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> <span class="hljs-string" style="color:#0880;box-sizing: border-box;">" "</span> <span class="hljs-subst" style="color:#000000;box-sizing: border-box;"><<</span> PrettyMethod(method);
        EnableXposedHook(env, method, additional_info);
    }</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></ul>

EnableXposedHook:

<code class="hljs cpp 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;">static</span> <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> EnableXposedHook(JNIEnv* env, ArtMethod* art_method, jobject additional_info)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {

      LOG(INFO) << <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"dexposed: >>> EnableXposedHook"</span> << art_method << <span class="hljs-string" style="color:#0880;box-sizing: border-box;">" "</span> << PrettyMethod(art_method);
      <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (dexposedIsHooked(art_method)) {
        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Already hooked</span>
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;
      }
<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//    else if (UNLIKELY(art_method->IsXposedOriginalMethod())) {</span>
<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//      // This should never happen</span>
<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//      ThrowIllegalArgumentException(nullptr, StringPrintf("Cannot hook the method backup: %s", PrettyMethod(art_method).c_str()).c_str());</span>
<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//      return;</span>
<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//    }</span>

      ScopedObjectAccess soa(env);

      <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Create a backup of the ArtMethod object</span>
      ArtMethod* backup_method = down_cast<ArtMethod*>(art_method->Clone(soa.Self()));
      <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Set private flag to avoid virtual table lookups during invocation</span>
      backup_method->SetAccessFlags(backup_method->GetAccessFlags() <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">/*| kAccXposedOriginalMethod*/</span>);
      <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Create a Method/Constructor object for the backup ArtMethod object</span>
      jobject reflect_method;
      <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (art_method->IsConstructor()) {
        reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Constructor);
      } <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">else</span> {
        reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Method);
      }
      env->SetObjectField(reflect_method, WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod,
          env->NewGlobalRef(soa.AddLocalReference<jobject>(backup_method)));
      <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Save extra information in a separate structure, stored instead of the native method</span>
      DexposedHookInfo* hookInfo = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">reinterpret_cast</span><DexposedHookInfo*>(<span class="hljs-built_in" style="color:#66066;box-sizing: border-box;">calloc</span>(<span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">sizeof</span>(DexposedHookInfo)));
      hookInfo->reflectedMethod = env->NewGlobalRef(reflect_method);
      hookInfo->additionalInfo = env->NewGlobalRef(additional_info);
      hookInfo->originalMethod = backup_method;

      jstring shorty = (jstring)env->GetObjectField(additional_info,additionalhookinfo_shorty_field);
      hookInfo->shorty = env->GetStringUTFChars(shorty, <span class="hljs-number" style="color:#06666;box-sizing: border-box;">0</span>);
      LOG(INFO) << <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"dexposed: >>> EnableXposedHook shorty:"</span> << hookInfo->shorty;

<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">#if PLATFORM_SDK_VERSION < 22</span>
        art_method->SetNativeMethod(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">reinterpret_cast</span><uint8_t *>(hookInfo));
<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">#else</span>
        art_method->SetEntryPointFromJni(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">reinterpret_cast</span><<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> *>(hookInfo));
<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">#endif</span>

      art_method->SetEntryPointFromQuickCompiledCode(GetQuickDexposedInvokeHandler());
<span class="hljs-comment" style="color:#8800;box-sizing: border-box;">//    art_method->SetEntryPointFromInterpreter(art::artInterpreterToCompiledCodeBridge);</span>
      <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Adjust access flags</span>
      art_method->SetAccessFlags((art_method->GetAccessFlags() & ~kAccNative) <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">/*| kAccXposedHookedMethod*/</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><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></ul>

通过: 
art_method->SetAccessFlags((art_method->GetAccessFlags()&~kAccNative)/| kAccXposedHookedMethod/); 
art_method->SetEntryPointFromQuickCompiledCode(GetQuickDexposedInvokeHandler()); 
同样也是把把实现指向native方法实现调度机制来达到目的。


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值