native method與so中function的關聯


在Android中,可以通過JNI的方式來調用和訪問用C/C++實現的代碼,這些代碼以SharedLibrary的方式存在於so中。從Java Code到Native Code的一般使用過程為:

  1. 在Java中的某個類中調用System.loadLibrary(XXX)(對於ing的so的全名應為:libXXX.so),或者System.load(soPathName)(soPathName對應於要加載的某個so的完整路徑及文件名)來加載so;
  2. 聲明所要調用的靜態方法,即需要和so中函數關聯的方法名:需要關鍵字native
  3. 編寫so,實現聲明的native method的功能。
  4. 與nativeMethod進行關聯:1)使用符合JNI規范的JNI Name String來作為so中的對應函數的函數名:一般為class_name_method_name的形式;2)在JNI_OnLoad中調用jniRegisterNativeMethods手動注冊,一半對於每個method需要提供信息:methodName, method signature, function(pointer).

本文則是總結native Method與so中的function如何建立關聯關系的:jin native method的注冊。對於完整注冊過程可參考老羅的博文Dalvik虛擬機JNI方法的注冊過程分析,其中已有詳盡的介紹。

通過jniRegisterNativeMethods的注冊

這個方式的注冊,是用戶在JNI_OnLoad中主動注冊完成的。重新學習注冊過程,了解了method的管理方法和調用方式。 注冊過程就是一個將native function綁定到一個native method,准確點說應該是將該native method結構中的DalvikBidgeFunc nativeFunc賦值為某一個jniBridge函數,然后將ins賦值為native function的函數地址。然后再調用時通過調用nativeFunc,即bridge函數,在此基礎上基於libffi,實現跨平台無差異化調用真正的對應的native function。 關於java 中method的結構可參考對Java中method和class的管理和組織方法。

在注冊過程中會,會根據注冊提供的信息--className、MethodName去發射獲取對象,查看需要綁定的對象和native method是否存在。

符合jni specification的本地函數的查找過程

相關代碼位於:dalvik/vm/native.cpp

由於此種方式的調用,java中的native method中的nativeFunc被初始化的設置為dvmResolveNativeMethod;(實際上每個method都被初始化為dvmResolveNativeMethod)。

所以首次運行時會調用dvmResolveNativeMethod嘗試去內部( dvmLookupInternalNativeMethod(method))以及已加載的so中嘗試獲取該相應的函數地址( lookupSharedLibMethod(method), 實際搜索過程在findMethodInLib中完成).如果是在lib中找到, 則通過dvmUseJNIBridge將method中的nativeFunc設置為相應的Bridge函數,ins設為func地址。

此后則無需搜索過程,直接調用即可。

對於在so中的函數搜索,判斷依據是lib和method有相同的classLoader,且method對應的JNI name string的函數存在於lib中.(這通過dlopen和dlsym嘗試獲取地址來判斷)。

參考

  1. 老羅 Dalvik虛擬機JNI方法的注冊過程分析
  2. AOSP source code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM