Android JNI 装载顺序

本文详细介绍了Android JNI的装载顺序,从具体调用代码到源码层面进行解析,帮助开发者理解这一过程。
摘要由CSDN通过智能技术生成

Android JNI 装载顺序

本篇文章主要是记录下JNI开发过程中,JNI装载的流程,便于以后进行更深层次的JNI开发时,可以更快的进行调试。
  1. 装载顺序
  2. 具体调用代码
  3. 源码查阅

1.装载顺序

  1. 从System.loadLibrary(“libname”);开始
  2. loadLibrary 中 调用 Runtime中的 loadLibrary0()方法
  3. 调用Runtime.java 中的doLoad
  4. 调用Runtime.java 中的JNI方法 nativeLoad
  5. 调用Runtime.c中的Runtime_NativeLoad
  6. Runtime_NativaLoad中调用 JVM_NativeLoad
  7. JVM_NativeLoad 中调用 JAVAVM中的LoadNativeLibrary方法
  8. LoadNativaLibrary方法中最终调用android::OpenNativeLibrary来加载动态库
  9. 并通过library中的FindSymbol找到动态库的初始化起点JNI_OnLoad保存到一个函数指针sym
  10. 通过JNI_OnLoadFn来执行该函数指针,这时候,So已加载完成,将会执行动态库中对应的JNI_OnLoad方法
  11. 我们可以在JNI_Onload方法中保存全局的gvm变量等,用于后续的开发

2. 具体调用代码

 1. System.loadLibrary(“libname”);
 2. @CallerSensitive
    public static void loadLibrary(String libname) {
   
        Runtime.getRuntime().loadLibrary0(VMStack.getCallingClassLoader(), libname);
    }
 3. synchronized void loadLibrary0(ClassLoader loader, String libname) {
   
	// 判断是否含有文件路径区分符,如果有,返回无法链接错误
        if (libname.indexOf((int)File.separatorChar) != -1) {
   
            throw new UnsatisfiedLinkError(
    "Directory separator should not appear in library name: " + libname);
        }
        String libraryName = libname;
		// 通常情况下 loader应不为空
        if (loader != null) {
   
			// 通过类加载器查找当前library库是否存在,可能是so或者dll
            String filename = loader.findLibrary(libraryName);
            if (filename == null) {
   
                // It's not necessarily true that the ClassLoader used
                // System.mapLibraryName, but the default setup does, and it's
                // misleading to say we didn't find "libMyLibrary.so" when we
                // actually searched for "liblibMyLibrary.so.so".
                throw new UnsatisfiedLinkError(loader + " couldn't find \"" +
                                               System.mapLibraryName(libraryName) + "\"");
            }
			// 加载library库
            String error = doLoad(filename, loader);
            if (error != null) {
   
                throw new UnsatisfiedLinkError(error);
            }
            return;
        }
		// 将传入的libraryName去除前面部分的lib,补上后缀so
        String filename = System.mapLibraryName(libraryName);
        List<String> candidates = new ArrayList<String>();
        String lastError = null;
		// getLibPaths 通过 System.getProperty("java.library.path"); 获取系统默认的library路径,在每个library路径中补上so库名称,然后尝试读取打开
        for (String directory : getLibPaths()) {
   
            String candidate = directory + filename;
            candidates.add(candidate);
			// 通过IO工具类尝试读出该路径下的so库
            if (IoUtils.canOpenReadOnly(candidate)) {
   
				// 加载library库
                String error = doLoad(candidate, loader);
                if (error == null) {
   
                    return; // We successfully loaded the library. Job done.
                }
                lastError = error;
            }
        }
       ……
    }
	
4.  // 通过调用nativaLoad进行library库加载 
	private String doLoad(String name, ClassLoader loader) {
   
       ……
        String librarySearchPath = null;
        if (loader != null && loader instanceof BaseDexClassLoader) {
   
            BaseDexClassLoader dexClassLoader 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值