雖然您可以完全使用Java編寫應用程序,但有些情況下Java本身并不能滿足您的應用程序的需求。當應用程序不能完全用Java編寫時,程序員使用JNI編寫Java本機方法來處理這些情況。
以下示例說明何時需要使用Java本機方法:
標準Java類庫不支持應用程序所需的與平臺相關的功能。
您已經有一個用另一種語言編寫的庫,并希望通過JNI使其可以訪問Java代碼。
您希望在較低級別的語言(如匯編語言)中實現一小部分時間關鍵代碼。
來源:https://docs.oracle.com/javase/1.5.0/docs/guide/jni/
開發平臺
芯靈思SinlinxA33開發板
淘寶店鋪: https://sinlinx.taobao.com/
嵌入式linux 開發板交流 QQ:641395230
了解JNI函數
JNI函數就是在native層定義的本地函數,對應于在java層使用native關鍵字聲明的方法的。直白的說,就是在Java層聲明,C/C++語言實現的。當然,這個函數并不一般,它會通過JNI某種機制與Java層的方法進行關聯,使得Java層代碼可以很方便的調用它。
jni函數的語法和調用規則
- 將java語言的數據類型轉換成底層語言調用規則
- 將java語言的方法調用轉換成底層語言函數或方法
jni數據類型的轉化
jni在java和C之間建立連接,因此jni首先要統一兩者的數據類型
Java Type | Native Type | Description |
---|---|---|
boolean | jboolean | unsigned 8 bits |
byte | jbyte | signed 8 bits |
char | jchar | unsigned 16 bits |
short | jshort | signed 16 bits |
int | jint | signed 32 bits |
long | jlong | signed 64 bits |
float | jfloat | 32 bits |
double | jdouble | 64 bits |
void | void | N/A |
The following definition is provided for convenience.
define JNI_FALSE 0 #define JNI_TRUE 1
The jsize integer type is used to describe cardinal indices and sizes:
typedef jint jsize;
- java中可以直接調用底層語言的函數,jni規定了java調用底層語言的方法簽名
- java中有重載概念,所以java方法轉換成簽名,簽名再轉化為函數
| Type Signature | Java Type |
| -------- | -------- | -------- |
| Z | boolean |
| B | byte |
| C | char |
| S | short |
| I | int |
| J | long |
| F | float |
| D | double |
| L | fully-qualified-class |
| [ type | type[] |
For example, the Java method:
long f (int n, String s, int[] arr);
has the following type signature:
(ILjava/lang/String;[I)J
jni機制實現
native 聲明的函數可以不實現
class Cls {
native double f(int i, String s); // 聲明為本地方法
static {
System.loadLibrary(“庫名”); // 通過靜態初始化語句塊來加載動態庫
}
}
程序實現測試java代碼
javah -jni Hello
生成Hello .h打開Hello .h 文件里面已經寫好C函數的名字
C代碼
將C文件制做成共享庫.so,注意指定jni.h和jni_md.h文件路徑
gcc -shared -fPIC hello.c -o libhello.so -I /usr/java/jdk1.6.0_45/include/ -I /usr/java/jdk1.6.0_45/include/linux/
java Hello
運行程序
實驗現象