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); } }

【android 加载so的流程】最终调用了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 行。
 

    推荐阅读