JNI使用規範

1、  JNI概述

JavaNative Interface的縮寫,中文爲Java本地調用。從Java1.1開始,JNI即成爲Java標準的一部分。 數組

JNI設計的目的是爲了容許Java代碼與其餘語言進行交互。但這樣作一般會致使喪失平臺可移植性,一般是在特定的需求下進行,例如使用舊的其餘語言的庫、須要得到Java類庫不支持的某種基於具體平臺的特性、大量數學計算性能優化等。 緩存

2、  JNI數據類型和數據結構

1.基本類型 性能優化

JNI基本類型和本地等效類型的對應表格以下: 數據結構

  

Java類型 函數

  

本地類型 性能

說明 優化

boolean 編碼

jboolean spa

無符號,8位 設計

byte

jbyte

無符號,8位

char

jchar

無符號,16位

short

jshort

有符號,16位

int

jint

有符號,32位

long

jlong

有符號,64位

float

jfloat

32位

double

jdouble

64位

void

void

爲了使用方便,還提供了以下定義:

#define JNI_FALSE 0

#define JNI_TRUE 1

Jsize類型用於描述主要指數和大小:

typedef jint jsize;

    2.引用類型

除了基本類型外,JNI還包含了很對對應於不一樣Java對象的引用類型,JNI引用類型的組織層次以下圖所示:


在C語言中,全部其餘JNI引用類型都被定義爲與jobject同樣,例如:

    typedef jobject jclass;

在C++中,JNI引入虛構類以增強子類關係,例如:

    class _jobject{};

    class _jstring : public jobject{};

    …

    typedef _jobject jobject;

    typedef _jstring jstring;

    3.方法ID和域ID

       方法ID和域ID是常規的C指針類型:

           struct_jmethodID;                     /*不透明結構*/

           typedefstruct _jmethodID *jmethodID;  /*方法ID*/

           struct_jfieldID;                      /*不透明結構*/

           typedefstruct _jfieldID *jfieldID     /*域ID*/

    4.值類型

       jvalue聯合在參數數組中用做單元類型,其聲明以下:

           typedefunion _jvalue

{

    jboolean z;

    jbyte b;

    jchar c;

    jshort s;

    jint i;

    jlong j;

    jfloat f;

    jdouble d;

    jobject l;

}jvalue;

    5.UTF8字符串

JNI的UTF8字符串與標準UTF8格式有兩個區別,第一,空字節0使用雙字節格式進行編碼,而不是標準UTF8的單字節;第二,只使用單字節、雙字節和三字節格式,不支持更長的字節格式。

3、  JNI接口函數命名方式

1. 類型簽名

Java虛擬機的類型簽名以下:

  

類型簽名

  

Java類型

Z

boolean

B

byte

C

char

S

short

I

int

J

long

F

float

D

double

Lfully-qulitied-class;

全限定類

[type

type[] 數組

(argtypes)rettype

方法類型

例如,Java方法int feet(int n, String s,int [] arr)的類型簽名以下:

(ILJava/lang/String;[I)I

圓括號裏面爲參數,I表示第一個參數int型,LJava/lang/String;表示第二個參數爲全限定Java.lang.String類型,[I表示第三個參數爲int型的數組,圓括號後面爲返回值類型,I表示返回值爲int型。

2. 通常函數的JNI接口函數命名方式

通常JNI接口函數命名以下:

    Java_包名_類名_方法名。

例如:某工程下Sample/test包下MySigal類的int GetASample()方法的C語言實現函數命名以下:

jint Java_Sample_test_MySigal_GetASample(JNIEnv* env,jobjectobj)

其中,包名所包含的「/」應所有如下劃線替代,其本地實現的參數和返回值也應轉換爲JNI類型。

3. 重載函數的JNI接口函數命名方式

重載函數的JNI實如今通常函數的JNI實現以外,還應添加上類型簽名以做爲同名函數之間的區別,其接口函數命名以下:

    Java_包名_類名_方法名_參數簽名。

例如:某工程下Sample/test包下MySigal類的int GetASample(int n, String s,int [] arr)方法的C語言實現函數命名以下:

jintJava_Sample_test_MySigal_GetASample_ILJava_lang_String_2_3I

(JNIEnv*env, jobject obj, jint n, jstring s, jintarray arr)。

JNI在函數命名時採用名字擾亂方案,以保證全部的Unicode字符都能轉換爲有效的C函數名,全部的「/」,不管是包名中的仍是全限定類名中的,均使用「_」代替,用_0,…,_9來代替轉義字符,以下:

  

轉義字符序列

  

表示

_0XXXX

Unicode字符XXXX

_1

字符「_」

_2

簽名中的字符「;」

_3

簽名中的字符「[」

4、  JNI函數與API

在目前的應用中,咱們所主要須要關心的是C/C++數據類型與JNI本地類型之間的轉化過程,這個過程某些數據的轉換須要使用JNIEnv對象的一系列方法來完成。

1.jstring轉換爲C風格字符串

char* test = (char*)(*env)->GetStringUTFChars(env,jstring,NULL);

使用完畢後,應調用:

(*env)->ReleaseStringUTFChars(env,jstring, test);

釋放資源。

2.C風格字符串轉換爲jstring

char charStr[50];

jstring jstr;

jstr = env ->NewStringUTF(charStr);

3.C語言中獲取的一段char*的buffer傳遞給Java

在jni中new一個byte數組,而後使用

(*env)->SetByteArrayRegion(env,bytearray, 0, len, buffer)

操做將buffer拷貝到數組中。

這種方式主要是針對buffer中存在「\0」的狀況,若是以C風格字符串的方式讀入,就會損失「\0」以後的字符。

4.數組操做

數組操做的相關函數列表以下:

  

JNI函數

  

功能

GetArrayLength

返回數組中的元素數

NewObjectArray

建立一個指定長度的原始數據類型數組

GetObjectArrayElement

返回Object數組的元素

SetObjectArrayElement

設置Object數組的元素

GetObjectArrayRegion

將原始數據類型數組中的內容拷貝到預先分配好的內存緩存中

SetObjectArrayRegion

設置緩存中數組的值

ReleaseObjectArrayRegion

釋放GetObjectArrayRegion分配的內存


對int,char等基本數據類型的數組操做,將相關Object名稱替換爲對應基本數據類型名稱即爲相關函數。

數組操做的方法選擇基於使用者的需求而定,若是使用者須要在內存中拷貝數組並對其進行操做那麼通常使用GetObjectArrayRegion和SetObjectArrayRegion函數,不然通常使用SetObjectArrayElement和GetObjectArrayElement函數。

相關文章
相關標籤/搜索