你真的瞭解 NDK 和 jni 的區別嗎

首先咱們要知道Java是如何調用c/c++的

Markdown
Markdown

什麼是JNI

java native interface(java本地接口)
ABI: application binary interface (應用程序二進制接口)java

簡介

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

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

#爲何要使用JNI程序員

  • 複用不少優秀的c/c++代碼
    • ffmpeg 多媒體播放器
    • opencv 圖形識別引擎
    • 7-zip 壓縮
    • opencore 視頻播放
  • 效率問題
    • java代碼跨平臺,不直接操做硬件,虛擬機解釋執行。垃圾回收機制。
    • art 在安裝apk應用程序的時候,把apk裏面的dex翻譯成機器碼(apk的體積會變大)
    • c代碼直接操做硬件,程序員能夠手工的釋放內存
  • 應用場景問題
    • c代碼能夠直接操做硬件。
    • java代碼只能操做虛擬機(一次編譯處處執行)
    • 智能家居操做硬件
    • 車載電腦(obd: onboard debug system)
  • 特殊業務邏輯
    • c代碼反編譯困難,調試困難。
    • java代碼反編譯容易,很容易看懂。

#怎麼使用JNI算法

  • 看懂c代碼( 有c語言基礎)
  • 懂流程 (熟悉jni的規範)
  • 熟練(NDK 工具 native develop kits)

開發工具

dev-cpp.exe 編程

  1. 輕量級開發工具
  2. 編譯器gcc c99標準

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

  • 一、編寫包含native本地方法的java類
  • 二、經過javah工具生成C/C++語言的頭文件
  • 三、使用C/C++語言實現頭文件
  • 四、使用交叉編譯工具對C/C++本地代碼進行編譯
  • 五、最後經過連接生成*.so可執行的C/C++庫

實際執行Java代碼去和本地的C/C++代碼互相溝通app

JNI中的JavaVM與JNIEnv對象

在標準的Java平臺下,每一個Process裏能夠產生不少JavaVM對象,每一個JavaVM對象都有一個與之對應的JavaVM對象,可是在Android平臺上,每一個Process只能產生一個DalvikVM對象,也就是說在一個Android的進程中是經過有且只有一個虛擬器對象來服務全部Java和C++代碼的。jvm

  • 一、JNIEnv 內部包含一個Pointer,Pointer指向Dalvik的JavaVM對象的Fanction Table,JNIEnv 關於程序執行環境的衆多函數正是來源於Dalvik虛擬機
  • 二、Android中每當一個Java線程第一次要調用本地C/C++代碼時,Dalvik虛擬機實例會爲該Java線程產生一個JNIEnv *指針
  • 三、Java每條線程在和C/C++互相調用時,JNIEnv是相互獨立的,互不干擾
    四、每本地的C/C++代碼想得到當前線程所要使用的JNIEnv時,可使用Dalvik VM對象的Java VM
    jvm->getEnv()方法,該方法即會返回當前線程所在的JNIEnv*
Java、Dalvik VM、C/C++的運行機制與流程 在Android的NDK中,Java、C/C++、Dalvik VM關係以下:
  • 一、java的dex字節碼和C/C++的*.so同時運行DalvikVM以內,共同使用一個進程空間。每次使用jni調用c/c++開闢一個線程去處理
  • 二、java和C/C++能夠相互調用,調用的關鍵是DalvikVM
  • 三、通常而言,比較經典的模式是Java經過JNI的C組建和C++相互溝通,通常業務處理放在C/C++中
  • 四、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層代碼。

NDK和jni的區別

對於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提供的庫和函數功能頗有限,僅僅處理些算法效率敏感的問題

    Markdown
    Markdown

相信本身,沒有作不到的,只有想不到的

若是你以爲此文對您有所幫助,歡迎入羣 QQ交流羣 :232203809
微信公衆號:終端研發部

技術+職場
技術+職場
相關文章
相關標籤/搜索