Android JNI 装载顺序
本篇文章主要是记录下JNI开发过程中,JNI装载的流程,便于以后进行更深层次的JNI开发时,可以更快的进行调试。
- 装载顺序
- 具体调用代码
- 源码查阅
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;
if (loader != null) {
String filename = loader.findLibrary(libraryName);
if (filename == null) {
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);
List<String> candidates = new ArrayList<String>();
String lastError = null;
for (String directory : getLibPaths()) {
String candidate = directory + filename;
candidates.add(candidate);
if (IoUtils.canOpenReadOnly(candidate)) {
String error = doLoad(candidate, loader);
if (error == null) {
return;
}
lastError = error;
}
}
……
}
4.
private String doLoad(String name, ClassLoader loader) {
……
String librarySearchPath = null;
if (loader != null && loader instanceof BaseDexClassLoader) {
BaseDexClassLoader dexClassLoader