首页 > 代码库 > android 加载so的流程

android 加载so的流程

源码版本:android-4.4.4_r1

以 [java.lang.Runtime -> load()] 为例来说明(loadLiabrary() 最后和 load() 殊途同归,有兴趣的可以自行分析),对应的 Android 源码在 [srcAndroid/libcore/luni/src/main/java/java/lang/Runtime.java/home/shanyu/srcAndroid/libcore/luni/src/main/java/java/lang/Runtime.java],

从 320 行开始。

    /**     * Loads and links the dynamic library that is identified through the     * specified path. This method is similar to {@link #loadLibrary(String)},     * but it accepts a full path specification whereas {@code loadLibrary} just     * accepts the name of the library to load.     *     * @param pathName     *            the absolute (platform dependent) path to the library to load.     * @throws UnsatisfiedLinkError     *             if the library can not be loaded.     */    public void load(String pathName) {        load(pathName, VMStack.getCallingClassLoader());    }    /*     * Loads and links the given library without security checks.     */    void load(String pathName, ClassLoader loader) {        if (pathName == null) {            throw new NullPointerException("pathName == null");        }        String error = doLoad(pathName, loader);        if (error != null) {            throw new UnsatisfiedLinkError(error);        }    }

最终调用了doLoad(String name, ClassLoader loader)函数,这个函数仍然在Runtime.java文件中:

    private String doLoad(String name, ClassLoader loader) {        // Android apps are forked from the zygote, so they can‘t have a custom LD_LIBRARY_PATH,        // which means that by default an app‘s shared library directory isn‘t on LD_LIBRARY_PATH.        // The PathClassLoader set up by frameworks/base knows the appropriate path, so we can load        // libraries with no dependencies just fine, but an app that has multiple libraries that        // depend on each other needed to load them in most-dependent-first order.        // We added API to Android‘s dynamic linker so we can update the library path used for        // the currently-running process. We pull the desired path out of the ClassLoader here        // and pass it to nativeLoad so that it can call the private dynamic linker API.        // We didn‘t just change frameworks/base to update the LD_LIBRARY_PATH once at the        // beginning because multiple apks can run in the same process and third party code can        // use its own BaseDexClassLoader.        // We didn‘t just add a dlopen_with_custom_LD_LIBRARY_PATH call because we wanted any        // dlopen(3) calls made from a .so‘s JNI_OnLoad to work too.        // So, find out what the native library search path is for the ClassLoader in question...        String ldLibraryPath = null;        if (loader != null && loader instanceof BaseDexClassLoader) {            ldLibraryPath = ((BaseDexClassLoader) loader).getLdLibraryPath();        }        // nativeLoad should be synchronized so there‘s only one LD_LIBRARY_PATH in use regardless        // of how many ClassLoaders are in the system, but dalvik doesn‘t support synchronized        // internal natives.        synchronized (this) {            return nativeLoad(name, loader, ldLibraryPath);        }    }    // TODO: should be synchronized, but dalvik doesn‘t support synchronized internal natives.    private static native String nativeLoad(String filename, ClassLoader loader, String ldLibraryPath);

最终调用到了"String nativeLoad(String filename, ClassLoader loader, String ldLibraryPath)"函数,这个一个native函数,定义位于[srcAndroid/dalvik/vm/native/java_lang_Runtime.cpp]文件中。从64行开始:

/* * static String nativeLoad(String filename, ClassLoader loader, String ldLibraryPath) * * Load the specified full path as a dynamic library filled with * JNI-compatible methods. Returns null on success, or a failure * message on failure. */static void Dalvik_java_lang_Runtime_nativeLoad(const u4* args,    JValue* pResult){    StringObject* fileNameObj = (StringObject*) args[0];    Object* classLoader = (Object*) args[1];    StringObject* ldLibraryPathObj = (StringObject*) args[2];    assert(fileNameObj != NULL);    char* fileName = dvmCreateCstrFromString(fileNameObj);    if (ldLibraryPathObj != NULL) {        char* ldLibraryPath = dvmCreateCstrFromString(ldLibraryPathObj);        void* sym = dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH");        if (sym != NULL) {            typedef void (*Fn)(const char*);            Fn android_update_LD_LIBRARY_PATH = reinterpret_cast<Fn>(sym);            (*android_update_LD_LIBRARY_PATH)(ldLibraryPath);        } else {            ALOGE("android_update_LD_LIBRARY_PATH not found; .so dependencies will not work!");        }        free(ldLibraryPath);    }    StringObject* result = NULL;    char* reason = NULL;    bool success = dvmLoadNativeCode(fileName, classLoader, &reason);    if (!success) {        const char* msg = (reason != NULL) ? reason : "unknown failure";        result = dvmCreateStringFromCstr(msg);        dvmReleaseTrackedAlloc((Object*) result, NULL);    }    free(reason);    free(fileName);    RETURN_PTR(result);}

还是传值 + 检查,然后执行 [bool success = dvmLoadNativeCode(fileName, classLoader, &reason);] ,看下 dvmLoadNativeCode(...) 的代码,位于 vm/Native.cpp # 301 行。

 

android 加载so的流程