JNI中load与loadLibrary的区别

  • load 和loadLibrary都是System类的方法
  • 作用都是加载需要使用的库文件
  • 类加载器都是通过Reflection.getCallerClass()获取
  • 最终调用的是nativeLoad方法
  • load需要传入加载类的绝对地址,loadLibrary只需传入类文件名

load方法源码

System中-->
  @CallerSensitive
    public static void load(String filename) {
        Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
    }

//最终调用Runtime中的load0方法,重点看load0即可
Runtime-->

synchronized void load0(Class fromClass, String filename) {
        if (!(new File(filename).isAbsolute())) {//此处判断如果文件路径名是否为绝对路径,不是则抛出异常
            throw new UnsatisfiedLinkError(
                "Expecting an absolute path of the library: " + filename);
        }
        if (filename == null) {
            throw new NullPointerException("filename == null");
        }
        String error = nativeLoad(filename, fromClass.getClassLoader());
        if (error != null) {
            throw new UnsatisfiedLinkError(error);
        }
    }

load总结:

  • load方法中会测试传入的抽象路径名是否为绝对路径。
  • 绝对路径名的定义取决于系统。
  • 在Android上,绝对路径以字符“ /”开头。
loadLibrary源码
System-->
 @CallerSensitive
    public static void loadLibrary(String libname) {
        Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
    }

Runtime-->
//最终调用Runtime中loadLibrary0
 private synchronized void loadLibrary0(ClassLoader loader, Class callerClass, String libname) {
        if (libname.indexOf((int)File.separatorChar) != -1) {//此方法判断libname中是否含有分隔符,有的话就抛出异常
            throw new UnsatisfiedLinkError(
    "Directory separator should not appear in library name: " + libname);
        }
        String libraryName = libname;
        // Android-note: BootClassLoader doesn't implement findLibrary(). http://b/111850480
        // Android's class.getClassLoader() can return BootClassLoader where the RI would
        // have returned null; therefore we treat BootClassLoader the same as null here.
        if (loader != null && !(loader instanceof BootClassLoader)) {
            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) + "\"");
            }
            String error = nativeLoad(filename, loader);
            if (error != null) {
                throw new UnsatisfiedLinkError(error);
            }
            return;
        }

        // We know some apps use mLibPaths directly, potentially assuming it's not null.
        // Initialize it here to make sure apps see a non-null value.
        getLibPaths();
        String filename = System.mapLibraryName(libraryName);
        String error = nativeLoad(filename, loader, callerClass);
        if (error != null) {
            throw new UnsatisfiedLinkError(error);
        }
    }

解析:

*  libname.indexOf((int)File.separatorChar) != -1 

File-->
   public static final char separatorChar = fs.getSeparator();
  • 获取文件中的文件名分隔符,强转成unicode值
  • 判断libname中是否含有分隔符,不含有则返回-1.
  • 所以不等于-1则抛出异常

loadLibrary总结

  • 需传入文件名的名称部分
  • 通过BootClassLoader子类的findLibrary方法返回绝对地址

你可能感兴趣的:(JNI中load与loadLibrary的区别)