Xposed源码剖析——Xposed初始化

承接上文 http://blog.csdn.net/yzzst/article/details/47829657

之前我们看过了app_main.cpp源码,知道了在其中,启动了XposedBridge.jar方法。那么,其中还做了些什么事情呢?

之前我们也看到了在app_main.cpp还有几处新增的逻辑。xposed::initialize和onVmCreated回调。下面我在仔细的阅读以下源码。

xposed::initialize初始化

对于xposed::initalize的初始化工作,我们能够在xposed.cpp中看到其具体的逻辑实现。

<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-comment" style="color:#8800;box-sizing: border-box;">/** 
 * 初始化xposed
 */</span>
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">bool</span> initialize(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">bool</span> zygote, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">bool</span> startSystemServer, <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>* className, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">int</span> argc, <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">char</span>* <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">const</span> argv[]) {
<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">#<span class="hljs-keyword" style="color:#444444;box-sizing: border-box;">if</span> !defined(XPOSED_ENABLE_FOR_TOOLS)</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!zygote)
        <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-preprocessor" style="color:#444444;box-sizing: border-box;">#<span class="hljs-keyword" style="color:#444444;box-sizing: border-box;">endif</span></span>

    xposed->zygote = zygote;
    xposed->startSystemServer = startSystemServer;
    xposed->startClassName = className;
    xposed->xposedVersionInt = xposedVersionInt;

<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">#<span class="hljs-keyword" style="color:#444444;box-sizing: border-box;">if</span> XPOSED_WITH_SELINUX</span>
    xposed->isSELinuxEnabled   = is_selinux_enabled() == <span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>;
    xposed->isSELinuxEnforcing = xposed->isSELinuxEnabled && security_getenforce() == <span class="hljs-number" style="color:#06666;box-sizing: border-box;">1</span>;
<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">#<span class="hljs-keyword" style="color:#444444;box-sizing: border-box;">else</span></span>
    xposed->isSELinuxEnabled   = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;
    xposed->isSELinuxEnforcing = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">false</span>;
<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">#<span class="hljs-keyword" style="color:#444444;box-sizing: border-box;">endif</span>  // XPOSED_WITH_SELINUX</span>

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (startSystemServer) {
        xposed::logcat::start();
    } <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> (zygote) {
        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// TODO Find a better solution for this</span>
        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Give the primary Zygote process a little time to start first.</span>
        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// This also makes the log easier to read, as logs for the two Zygotes are not mixed up.</span>
        sleep(<span class="hljs-number" style="color:#06666;box-sizing: border-box;">10</span>);
    }

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 打印rom信息</span>
    printRomInfo();

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (startSystemServer) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!xposed::service::startAll())
            <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-preprocessor" style="color:#444444;box-sizing: border-box;">#<span class="hljs-keyword" style="color:#444444;box-sizing: border-box;">if</span> XPOSED_WITH_SELINUX</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> (xposed->isSELinuxEnabled) {
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!xposed::service::startMembased())
            <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-preprocessor" style="color:#444444;box-sizing: border-box;">#<span class="hljs-keyword" style="color:#444444;box-sizing: border-box;">endif</span>  // XPOSED_WITH_SELINUX</span>
    }

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// FIXME Zygote has no access to input devices, this would need to be check in system_server context</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (zygote && !isSafemodeDisabled() && detectSafemodeTrigger(shouldSkipSafemodeDelay()))
        disableXposed();

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (isDisabled() || (!zygote && shouldIgnoreCommand(argc, argv)))
        <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;">// 将XposedBridge.jar的路径添加到环境变量classpath中</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> addJarToClasspath();
}</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></ul>

* onVmCreated 初始化后的准备工作 *

其具体的逻辑如下所示:

<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-javadoc" style="color:#8800;box-sizing: border-box;">/**   
  * 向当前的runtime中载入libxposed_*.so 
  */</span>
<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> onVmCreated(JNIEnv* env) {
    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Determine the currently active runtime</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>* xposedLibPath = NULL;
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!determineRuntime(&xposedLibPath)) {
        ALOGE(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Could not determine runtime, not loading Xposed"</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;">// Load the suitable libxposed_*.so for it</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> *error;
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span>* xposedLibHandle = dlopen(xposedLibPath, RTLD_NOW);
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!xposedLibHandle) {
        ALOGE(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Could not load libxposed: %s"</span>, dlerror());
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;
    }

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Clear previous errors</span>
    dlerror();

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// Initialize the library</span>
    bool (*xposedInitLib)(XposedShared* shared) = NULL;
    *(<span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">void</span> **) (&xposedInitLib) = dlsym(xposedLibHandle, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"xposedInitLib"</span>);
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!xposedInitLib)  {
        ALOGE(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Could not find function xposedInitLib"</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;">if</span> XPOSED_WITH_SELINUX
    xposed->zygoteservice_accessFile = &service::membased::accessFile;
    xposed->zygoteservice_statFile   = &service::membased::statFile;
    xposed->zygoteservice_readFile   = &service::membased::readFile;
#endif  <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// XPOSED_WITH_SELINUX</span>

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 这里的xposed变量,其实是一个全局的XposedShare。</span>
    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 调用XposedShare的onVmCreated则会根据不同的vm架构针对不同的实现。</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (xposedInitLib(xposed)) {
        xposed->onVmCreated(env);
    }
}</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></ul>

* libxposed_dalvik.cpp hook环境初始化*

<code class="hljs scala 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-javadoc" style="color:#8800;box-sizing: border-box;">/** Called by Xposed's app_process replacement. 
  * 在被替换后的app_process中调用
  */</span>
bool xposedInitLib(xposed::XposedShared* shared) {
    xposed = shared;
    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 将自己的onVmCreated方法,指向onVmCreated方法</span>
    xposed->onVmCreated = &onVmCreated;
    <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-javadoc" style="color:#8800;box-sizing: border-box;">/** Called very early during VM startup. 
  * 在VM启动的时候调用,而且调用时机比较早
  */</span>
void onVmCreated(JNIEnv* env) {
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (!initMemberOffsets(env))
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 找到小米系统的MIUI_RESOURCE做特殊处理</span>
    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">class</span> <span class="hljs-title" style="color:#66066;box-sizing: border-box;">classMiuiResources</span> = <span class="hljs-title" style="color:#66066;box-sizing: border-box;">env</span>-><span class="hljs-title" style="color:#66066;box-sizing: border-box;">FindClass</span><span class="hljs-params" style="color:#66066;box-sizing: border-box;">(CLASS_MIUI_RESOURCES)</span>;</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (classMiuiResources != NULL) {
        ClassObject* clazz = (ClassObject*)dvmDecodeIndirectRef(dvmThreadSelf(), classMiuiResources);
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (dvmIsFinalClass(clazz)) {
            ALOGD(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Removing final flag for class '%s'"</span>, CLASS_MIUI_RESOURCES);
            clazz->accessFlags &= ~ACC_FINAL;
        }
    }
    env->ExceptionClear();

    j<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">class</span> <span class="hljs-title" style="color:#66066;box-sizing: border-box;">classXTypedArray</span> = <span class="hljs-title" style="color:#66066;box-sizing: border-box;">env</span>-><span class="hljs-title" style="color:#66066;box-sizing: border-box;">FindClass</span><span class="hljs-params" style="color:#66066;box-sizing: border-box;">(CLASS_XTYPED_ARRAY)</span>;</span>
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (classXTypedArray == NULL) {
        ALOGE(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Error while loading XTypedArray class '%s':"</span>, CLASS_XTYPED_ARRAY);
        dvmLogExceptionStackTrace();
        env->ExceptionClear();
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;
    }
    prepareSubclassReplacement(classXTypedArray);

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 获取到全局的XposedBridge</span>
    classXposedBridge = env->FindClass(CLASS_XPOSED_BRIDGE);
    classXposedBridge = reinterpret_cast<jclass>(env->NewGlobalRef(classXposedBridge));

    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (classXposedBridge == NULL) {
        ALOGE(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Error while loading Xposed class '%s':"</span>, CLASS_XPOSED_BRIDGE);
        dvmLogExceptionStackTrace();
        env->ExceptionClear();
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;
    }

    <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 注册一些 XposedBridge 的 native 方法</span>
    ALOGI(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Found Xposed class '%s', now initializing"</span>, CLASS_XPOSED_BRIDGE);
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">if</span> (register_natives_XposedBridge(env, classXposedBridge) != JNI_OK) {
        ALOGE(<span class="hljs-string" style="color:#0880;box-sizing: border-box;">"Could not register natives for '%s'"</span>, CLASS_XPOSED_BRIDGE);
        dvmLogExceptionStackTrace();
        env->ExceptionClear();
        <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span>;
    }

    xposedLoadedSuccessfully = <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">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><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></ul>

JNI方法注册逻辑

这里注册的几个方法都是,Xposed核心的几个方法函数。

<code class="hljs vala 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;">int</span> register_natives_XposedBridge(JNIEnv* env, jclass clazz) {
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">const</span> JNINativeMethod methods[] = {

        NATIVE_METHOD(XposedBridge, getStartClassName, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"()Ljava/lang/String;"</span>),
        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 获得Runtime</span>
        NATIVE_METHOD(XposedBridge, getRuntime, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"()I"</span>),
        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 启动SystemServer</span>
        NATIVE_METHOD(XposedBridge, startsSystemServer, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"()Z"</span>),
        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 获取Xposed的版本信息</span>
        NATIVE_METHOD(XposedBridge, getXposedVersion, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"()I"</span>),
        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// 初始化navtive</span>
        NATIVE_METHOD(XposedBridge, initNative, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"()Z"</span>),
        <span class="hljs-comment" style="color:#8800;box-sizing: border-box;">// hook一个方法的native实现</span>
        NATIVE_METHOD(XposedBridge, hookMethodNative, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"(Ljava/lang/reflect/Member;Ljava/lang/Class;ILjava/lang/Object;)V"</span>),
<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">#ifdef ART_TARGET</span>
        NATIVE_METHOD(XposedBridge, invokeOriginalMethodNative,
            <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"(Ljava/lang/reflect/Member;I[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"</span>),
<span class="hljs-preprocessor" style="color:#444444;box-sizing: border-box;">#endif</span>
        NATIVE_METHOD(XposedBridge, setObjectClassNative, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"(Ljava/lang/Object;Ljava/lang/Class;)V"</span>),
        NATIVE_METHOD(XposedBridge, dumpObjectNative, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"(Ljava/lang/Object;)V"</span>),
        NATIVE_METHOD(XposedBridge, cloneToSubclassNative, <span class="hljs-string" style="color:#0880;box-sizing: border-box;">"(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;"</span>),
    };
    <span class="hljs-keyword" style="color:#0088;box-sizing: border-box;">return</span> env->RegisterNatives(clazz, methods, NELEM(methods));
}</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></ul>

我们看到RegisterNatives这个方法的时候不是很理解,这里做一个简介。

以前在jni中写本地方法时,都会写成 Java_com_example_hellojni_HelloJni_stringFromJNI的形式,函数名很长,而且当类名变了的时候,函数名必须一个一个的改,麻烦。 
现在好了有了RegisterNatives,可以简化我们的书写 
和传统方法相比,使用RegisterNatives的好处有三点: 
1. C++中函数命名自由,不必像javah自动生成的函数声明那样,拘泥特定的命名方式; 
2. 效率高。传统方式下,Java类call本地函数时,通常是依靠VM去动态寻找.so中的本地函数(因此它们才需要特定规则的命名格式),而使用RegisterNatives将本地函数向VM进行登记,可以让其更有效率的找到函数; 
3. 运行时动态调整本地函数与Java函数值之间的映射关系,只需要多次call RegisterNatives()方法,并传入不同的映射表参数即可。


原文地址: http://blog.csdn.net/yzzst/article/details/47834077

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值