日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java Native Interface 二 JNI中对Java基本类型和引用类型的处理

發布時間:2025/4/9 java 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java Native Interface 二 JNI中对Java基本类型和引用类型的处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文是《The Java Native Interface Programmer’s Guide and Specification》讀書筆記

Java編程里會使用到兩種類型:基本類型(如int,float等)和引用類型(如class,instance,arrays),JNI編程里對這兩種的類型的處理方法也是不一樣的。

JNI定義了與Java的基本類型和引用類型相對應的C/C++類型:

Java類型本地類型(JNI中使用)
booleanjboolean
intjint
floatjfloat
bytejbyte
charjchar
shortjshort
longjlong
doublejdouble

Java中所有對象都是Object類的子類,在JNI中與之對應的為jobject類,所有的類型都是jobject類的子類,直接繼承自jobject 的引用類型:

Java類型本地類型
java.lang.Classjclass
java.lang.Stringjstring
arraysjarray
java.lang.Throwablejthrowable

其中數組又會有其他的子類型,如Java中的int[] 對應到JNI中為jintArray,Object[]對應為jobjectArray[]等;

在使用C++時,類的繼承的語法為

class _jobjct{}; class _jclass:public_jobjct{};//公有繼承

同時在JNI中會使用類標識符來表示Java中的類或接口。數組用'['來標識,如int[]在JNI中用'[I'來標識,三維數組double[][][],用['[[[D'來標識;下面是JNI中常用基本類型的標識符與對應的Java類:

成員域標識符Java 類型
Zboolean
Bbyte
Cchar
Sshort
Iint
Jlong
Ffloat
Ddouble

JNI中引用類型的標識符以字符'L'開始,并以';'結束,但數組的標識符與前面的基本類型的標識符相同;

標識符Java類型
"Ljava/lang/String;"String
"[I"int[]
"[Ljava/lang/Object;"Object[]

在JNI中方法的標識符里,方法所含的參數之間是沒有空格隔開的,并用字符"V"作為void方法的返回標識;構造函數一般使用"V"作為返回值,"init"作為名字;

方法標識符Java方法
"()Ljava/lang/String; "String f()
"(ILjava/lang/Class;)J"long f(int i,Class c)
"([B)V"String(byte[]bytes)

在了解完JNI中對應的類型與標識符后,接下來就是怎樣使用它們了。

String類型的使用

在實現本地方法時,必須使用JNI的方法將對應的jstring對象類型轉型為c/c++可以識別的string 對象,否則在調用這個本地方法時會導致Java虛擬機崩潰;
假設有一個本地方法,在Java里聲明為:

public native String getLine(String promt);

則你在實現這個方法時,不能這樣寫:

JNIEXPORT jstring JNICALL Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt) {/* ERROR: incorrect use of jstring as a char* pointer */printf("%s", prompt);... }

你可以這樣寫:

JNIEXPORT jstring JNICALL Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt) {char buf[128];const jbyte *str;str = (*env)->GetStringUTFChars(env, prompt, NULL);//必須要記得檢查JNI方法的返回值,因為JVM在執行時需要分配內存,可能存在內存分配失敗的情況if (str == NULL) {return NULL; /* OutOfMemoryError already thrown */}printf("%s", str);//當使用完JNI方法返回的對象后,調用相應的Release方法釋放掉對應的內 存,忘記使用Release方法可能會導致內存泄漏(*env)->ReleaseStringUTFChars(env, prompt, str);/* We assume here that the user does not type more than* 127 characters */scanf("%s", buf);return (*env)->NewStringUTF(env, buf); }

jni中的可以對String(jstring)對象使用的方法總結:

方法名方法描述
GetStringChars,ReleaseStringChars獲取或釋放一個指向Unicode編碼的字符串內容的指針,可能會返回一個字符串的拷貝
GetStringUTFChars,ReleaseStringUTFChars獲取或釋放一個指向UTF-8編碼的字符串內容的指針,可能會返回一個字符串的拷貝
GetStrinLength返回字符串里Unicode編碼的字符的個數
GetStringUTFLength返回字符串里UTF-8編碼的字符的個數
NewString創建一個包含給定的Unicode編碼的C字符串的所有字符的java.lang.String實例
NewStringUTF創建一個包含給定的UTF-8編碼的C字符串的所有字符的java.lang.String實例
GetStringCritical,ReleaseStringCritical獲取一個指向Unicode編碼的字符串內容的指針,可能返回一個字符串的拷貝。并且本地代碼在調用Get/ReleaseStrinCritical這對方法時,不能阻塞。
GetStringUTFRegion,SetStringUTFRegion從一個預先分配的UTF-8格式的C的緩沖區拷貝字符串內容(或將字符串內容寫入緩沖區中)

Arrays類型的使用

JNI對普通數組(基本類型的數組,如int[],float[])和對象數組的處理方法是不一樣的。下面以簡單的例子來說明:

1 普通的數組的使用

求一個數組的和的例子:Java Class為:

class IntArray {private native int sumArray(int[] arr);//jni方法,求數組的和public static void main(String[] args) {IntArray p = new IntArray();int arr[] = new int[10];for (int i = 0; i < 10; i++) {arr[i] = i;}int sum = p.sumArray(arr);System.out.println("sum = " + sum);}static {System.loadLibrary("IntArray");} }

Java的Arrays在JNI中用jarrays和它的子類,如jintArray來表示,就像jstring不是C字符串的類型,jarrays也不是C的數組類型,因此,你不能在實現JNI方法時,直接使用jarrays的引用,下面是錯誤的JNI方法的編寫:

JNIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr) {int i, sum = 0;for (i = 0; i < 10; i++) {sum += arr[i];} }

正確的JNI的方法應該為:

JNIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr) {jint buf[10];jint i, sum = 0;(*env)->GetIntArrayRegion(env, arr, 0, 10, buf);for (i = 0; i < 10; i++) {sum += buf[i];}return sum; }

也可以這樣寫:

JNIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr) {jint *carr;jint i, sum = 0;carr = (*env)->GetIntArrayElements(env, arr, NULL);if (carr == NULL) {return 0; /* exception occurred */}for (i=0; i<10; i++) {sum += carr[i];}(*env)->ReleaseIntArrayElements(env, arr, carr, 0);return sum; }

JNI中可以對基本類型數組使用的方法有:

:表示需要用基本類型來替代,如GetArrayRegion,就可以有GetIntArrayRegion,GetFloatArrayRegion等;

方法名方法描述
GetArrayRegion,SetArrayRegion得到基本類型的數組的內容,或將內容寫入預先分配的C的緩沖區里
GetArrayElements,ReleaseArrayElements獲得一個指向基本類型數組的內容的指針,可能會返回一個數組的拷貝
GetArrayLength返回數組的大小
NewArray創建一個給定長度的數組
GetPrimitiveArrayCritical,ReleasePrimitiveArrayCritical獲得或釋放指向基本類型數組的內容的指針

2 對象數組的使用:

JNI提供了許多對方法來得到對象數組。GetObjectElement方法會返回一個給定位置的元素,SetObjectElement方法更新給定位置的元素。但我們不能一次性就得到(復制)所有的對象數組里的元素。下面還是以簡單的例子來說明:
Java Class為:

class ObjectArrayTest {//本地方法,用來生成一個給定大小的二維矩陣private static native int[][] initInt2DArray(int size);public static void main(String[] args) {int[][] i2arr = initInt2DArray(3);for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {System.out.print(" " + i2arr[i][j]);}System.out.println();}}static {System.loadLibrary("ObjectArrayTest");} }

本地方法的實現為:

JNIEXPORT jobjectArray JNICALL Java_ObjectArrayTest_initInt2DArray(JNIEnv *env,jclass cls,int size) {jobjectArray result;int i;//獲得一個元素類型(Int)的Class引用,類似于Java中得到某一類型的類加載器jclass intArrCls = (*env)->FindClass(env, "[I");if (intArrCls == NULL) {return NULL; /* exception thrown */}//生成一個元素類型為intArrCls的數組,這個方法只能生成一維數組result = (*env)->NewObjectArray(env, size, intArrCls, NULL);if (result == NULL) {return NULL; /* out of memory error thrown */}for (i = 0; i < size; i++) {jint tmp[256]; /* make sure it is large enough! */int j;//生成數組里存放的元素(仍然為一個數組)jintArray iarr = (*env)->NewIntArray(env, size);if (iarr == NULL) {return NULL; /* out of memory error thrown */}for (j = 0; j < size; j++) {tmp[j] = i + j;}//用tmp里的元素填充iarr數組,使用的是基本類型數組的方法(*env)->SetIntArrayRegion(env, iarr, 0, size, tmp);//將iarr作為數組元素填充到result數組相應位置中,使用的是對象數 組的方法(*env)->SetObjectArrayElement(env, result, i, iarr);//釋放到對iarr對象的引用(*env)->DeleteLocalRef(env, iarr);}//二維數組就是數組里存放的元素仍然為數組,返回一個對象數組return result; }

轉載于:https://www.cnblogs.com/WoodJim/p/4794772.html

總結

以上是生活随笔為你收集整理的Java Native Interface 二 JNI中对Java基本类型和引用类型的处理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。