NDK 與 JNI 的關係

  JNI是java語言提供的Java和C/C++相互溝通的機制,Java可以通過JNI調用本地的C/C++代碼,本地的C/C++的代碼也可以調用java代碼。JNI 是本地編程接口,Java和C/C++互相通過的接口。Java通過C/C++使用本地的代碼的一個關鍵性原因在於C/C++代碼的高效性。

NDK是一系列工具的集合。它提供了一系列的工具,幫助開發者快速開發C(或C++)的動態庫,並能自動將so和java應用一起打包成apk。這些工具對開發者的幫助是巨大的。它集成了交叉編譯器,並提供了相應的mk文件隔離CPU、平臺、ABI等差異,開發人員只需要簡單修改mk文件(指出“哪些文件需要編譯”、“編譯特性要求”等),就可以創建出so。它可以自動地將so和Java應用一起打包,極大地減輕了開發人員的打包工作。


Java通過JNI機制和C/C++溝通的具體步驟

1、編寫包含native本地方法的java類
2、通過javah工具生成C/C++語言的頭文件
3、使用C/C++語言實現頭文件
4、使用交叉編譯工具對C/C++本地代碼進行編譯,最後通過鏈接生成*.so可執行的C/C++庫
5、實際執行Java代碼去和本地的C/C++代碼互相溝通


JNI中的JavaVM與JNIEnv對象

在標準的Java平臺下,每個Process裏可以產生很多JavaVM對象,每個JavaVM對象都有一個與之對應的JavaVM對象,但是在Android平臺上,每個Process只能產生一個DalvikVM對象,也就是說在一個Android的進程中是通過有且只有一個虛擬器對象來服務所有Java和C++代碼的。
1、JNIEnv *內部包含一個Pointer,Pointer指向Dalvik的JavaVM對象的Fanction Table,JNIEnv *關於程序執行環境的衆多函數正是來源於Dalvik虛擬機
2、Android中每當一個Java線程第一次要調用本地C/C++代碼時,Dalvik虛擬機實例會爲該Java線程產生一個JNIEnv *指針
3、Java每條線程在和C/C++互相調用時,JNIEnv*是相互獨立的,互不干擾
4、每本地的C/C++代碼想獲得當前線程所要使用的JNIEnv時,可以使用Dalvik VM對象的Java VM* jvm->getEnv()方法,該方法即會返回當前線程所在的JNIEnv*

Java、Dalvik VM、C/C++的運行機制與流程

在Android的NDK中,Java、C/C++、Dalvik VM關係如下:
1、java的dex字節碼和C/C++的*.so同時運行DalvikVM之內,共同使用一個進程空間。每次使用jni調用c/c++開闢一個線程去處理
2、java和C/C++可以相互調用,調用的關鍵是DalvikVM
3、一般而言,比較經典的模式是Java通過JNI的C組建和C++相互溝通,一般業務處理放在C/C++中
4、C++代碼處於核心控制地位更具價值

當java需要C/C++代碼時,在DalvikVM虛擬機中加載動態鏈接庫時,會先調用JNI_Onload()函數,此時就會把javaVM對象的指針存儲於C層JNI組建的全局環境中,在JAVA層調用C層的本地庫函數時,調用C本地函數線程必然通過Dalvik VM來調用C本地函數,測試Dalvik虛擬機會爲本地的C組建實例化一個JNIEnv指針,該指針指向Dalvik虛擬機的具體函數列表,當JNI的C組件調用java層方法和屬性時,需要通過JNIEnv指針來進行調用。

當C++組件主動調用Java層方法時,需要通過JNI的C組件把JNIEnv指針傳遞給C++組件,此後,c++組件即可通過JNIEnv指針來掌控Java層代碼。

總結

對於JNI和NDK很多Android開發初學者沒有搞明白這個問題,JNI是Java調用Native機制,是Java語言自己的特性全稱爲Java Native Interface,類似的還有微軟.Net Framework上的p/invoke,可以讓C#或Visual Basic.Net可以調用C/C++的API,所以說JNI和Android沒有關係,在PC上開發Java的應用,如果運行在Windows平臺使用JNI是是經常的,比如說讀寫Windows的註冊表。而NDK是Google公司推出的幫助Android開發者通過C/C++本地語言編寫應用的開發包,包含了C/C++的頭文件、庫文件、說明文檔和示例代碼,我們可以理解爲Windows Platform SDK一樣,是純C/C++編寫的,但是Android並不支持純C/C++編寫的應用,同時NDK提供的庫和函數功能很有限,僅僅處理些算法效率敏感的問題,所以Android123推薦初學者學好Java後再學習JNI。

簡單點說,用C語言生成一個庫文件,在java中調用這個庫文件的函數。JNI的過程比較複雜,生成.so需要大量操作,而NDK就是簡化了這個過程。

發佈了145 篇原創文章 · 獲贊 92 · 訪問量 91萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章