2

首先,在 System.java 中,它调用 Runtime 来加载库。

public static void loadLibrary(String libName) {
    SecurityManager smngr = System.getSecurityManager();
    if (smngr != null) {
        smngr.checkLink(libName);
    }
    Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
}

其次,它调用VMStack.getCallingClassLoader()来findLibrary。

void loadLibrary(String libraryName, ClassLoader loader) {
    if (loader != null) {
        String filename = loader.findLibrary(libraryName);
        if (filename == null) {
            throw new UnsatisfiedLinkError("Couldn't load " + libraryName + ": " +
                    "findLibrary returned null");
        }
        //....
    }
}

所以,我认为VMStack.getCallingClassLoader()是最有意义的。但在其 jni 文件dalvik_system_VMStack.cpp中,该Dalvik_dalvik_system_VMStack_getCallingClassLoader函数很难学习。最后,dalvik 如何找到Library?

static void Dalvik_dalvik_system_VMStack_getCallingClassLoader(const u4* args,
    JValue* pResult){
    ClassObject* clazz =
        dvmGetCaller2Class(dvmThreadSelf()->interpSave.curFrame);

    UNUSED_PARAMETER(args);

    if (clazz == NULL)
        RETURN_PTR(NULL);
    RETURN_PTR(clazz->classLoader);
}
4

1 回答 1

7

VMStack.getCallingClassLoader()返回声明调用当前方法的方法的类的类加载器。换句话说,如果我的函数foo()调用Runtime.loadLibrary(),它将返回foo的类加载器。

所有这一切的重点是确保在调用者的上下文中加载库findLibrary,而不是在java.lang.Runtime.

很有可能findLibrary()是由 实现的BaseDexClassLoader,它调用了DexPathList.findLibrary(),它完成了实际工作。有趣的一点是遍历,它是从构造函数的参数nativeLibraryDirectories初始化的(从or获取它)。libraryPathBaseDexClassLoaderPathClassLoaderDexClassLoader

对于 Android 应用程序,请查看android.app.ApplicationLoaders,它使用PathClassLoader. 如果你追溯得足够远,你会看到从ApplicationInfo.nativeLibraryDir.

编辑:更深入地解决评论......

/system/lib来自核心库从环境变量中java.library.path提取的属性。LD_LIBRARY_PATH特定于应用程序的库目录由框架配置。

构造PackageManagerService函数设置 lib 路径mAppLibInstallDir,并setInternalAppNativeLibraryPath()配置nativeLibraryDir.

DexPathList.splitLibraryPath()java.library.path路径与特定于 APK 的路径组合在一起。有关订购的说明,请参阅那里的评论。

于 2013-03-29T19:49:38.220 回答