1. 爲什麼需要native?
2. java層(或者說dalvik)如何識別native函數?
3. java層到native的調用是如何實現的?
4. java和native工作在同一進程嗎?
5. native 受dalvik管理嗎?
帶着這些問題,接下來逐步去分析總結,相信是會有收穫的。
一、爲什麼需要native。
1. 不可反編譯。native 編譯出來的是目標代碼,不可反編譯。java編譯出來的中間代碼可反編譯,可反編譯可能會導致自己設計思想或者設計算法泄露,很多商業公司是極力避免的。
2. 執行速度快。native 代碼一般用c/c++ 實現,執行速度上要比java快些。
3. 方便移植。有些應用在沒有android之前,都是用c/c++ 開發的,那麼現在要移植到android上,直接移植到native層就不需要另外編寫java代碼,省時省力。
二、java(或者說dalvik)如何識別native函數
native函數聲明會帶有native字符,如下例子:
private static
native long nativeInit(InputManagerService service,
Context context, MessageQueue messageQueue);
這樣編譯的時候就把這個native標誌位加入到java 函數符號表裏,這樣就可以和普通的函數區分開了,運行過程虛擬機執行到native函數時就會切換到native執行環境。執行環境是如何切換的呢?還沒研究過。
三、java到native的調用是如何實現的
1. 每個虛擬機進程都對應一個JNI環境(JNIEnv)
2. 每個native方法都需要向這個JNI環境測試註冊
3. 這些native方法及實現會被編譯成一個動態庫
4.java層在執行到native代碼前需要把這個動態庫load進來。之後整個虛擬機進程的JNI環境就包含了native方法入口。
5. java層在執行到native代碼時就能通過JNI環境知道native層對應實現。
接下以事件輸入系統爲例做下分析:
1. native 方法定義數組,格式如下,第一個字段對應的是在java層函數名,第二個是函數形式參數縮寫,第三個是native層對應的函數名。
java 層函數形參和native層是有區別的,需要做轉換。下面是基本類型轉換
縮寫 | native 層 | java 層 |
V | void | void |
Z | jboolean | boolean |
I | jint | int |
J | jlong | long |
D | jdouble | double |
F | jfloat | float |
B | jbyte | byte |
C | jchar | char |
S | jshort | short |
[I | jintArray | int[] |
[F | jfloatArray | float[] |
[B | jbyteArray | byte[] |
[C | jcharArray | char[] |
[S | jshortArray | short[] |
[D | jdoubleArray | double[] |
[J | jlongArray | long[] |
[Z | jbooleanArray | Boolean[] |