本文共 2955 字,大约阅读时间需要 9 分钟。
终于建了一个自己个人小站:,以后优先更新小站博客,欢迎进站,O(∩_∩)O~~
JNI_OnLoad是在加载so的时候调用的,也就是System.loadLibrary("test")时候调用的。具体调用步骤如下:
System.loadLibrary(libName)->Runtime.loadLibrary(libName,classLoader)->Runtime.doLoad(libName,loader)->Runtime.nativeLoad(name,loader,ldLibraryPath)->JavaVMExt.loadNativieLibrary:(JavaVMExt* vm=Runtime::Current()->GetJavaVM(); vm->LoadNativieLibrary(filename,classloader,detail))->jni_internal.cc::LoadNativieLibrary->dlopen,dlsym->JNI_OnLoad。
以上给出了调用顺序,具体代码可以根据类名或方法名看出。有兴趣的可以自己查看下源码。
在Runtime.loadLibrary中,会在多个多个路径下寻找对应的so,只要找到了就会去加载,加载成功就会返回。对应代码如下:
Runtime.java
/* * Searches for and loads the given shared library using the given ClassLoader. */ void loadLibrary(String libraryName, ClassLoader loader) { if (loader != null) { 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 = doLoad(filename, loader); if (error != null) { throw new UnsatisfiedLinkError(error); } return; } String filename = System.mapLibraryName(libraryName); ListmLibPaths初始化代码如下:candidates = new ArrayList (); String lastError = null; for (String directory : mLibPaths) { String candidate = directory + filename; candidates.add(candidate); if (IoUtils.canOpenReadOnly(candidate)) { String error = doLoad(candidate, loader); if (error == null) { return; // We successfully loaded the library. Job done. } lastError = error; } } if (lastError != null) { throw new UnsatisfiedLinkError(lastError); } throw new UnsatisfiedLinkError("Library " + libraryName + " not found; tried " + candidates); }
/** * Holds the library paths, used for native library lookup. */ private final String[] mLibPaths = initLibPaths(); private static String[] initLibPaths() { String javaLibraryPath = System.getProperty("java.library.path"); if (javaLibraryPath == null) { return EmptyArray.STRING; } String[] paths = javaLibraryPath.split(":"); // Add a '/' to the end of each directory so we don't have to do it every time. for (int i = 0; i < paths.length; ++i) { if (!paths[i].endsWith("/")) { paths[i] += "/"; } } return paths; }
转载地址:http://ceutx.baihongyu.com/