亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何進行JNI的使用

發布時間:2022-01-06 18:47:02 來源:億速云 閱讀:165 作者:柒染 欄目:網絡安全

這篇文章給大家介紹如何進行JNI的使用,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

Java Native Interface(JNI) 是一種使用java語言和原生C/C++語言相互調用、混合編程的方法,它允許在Java虛擬機(VM)內運行的Java代碼與應用其他編程語言(如C、C++和匯編)編寫的應用程序和庫進行互操作,它支持從動態鏈接庫中加載代碼, 并能使用C/C++的高效的特性。

如果要基本了解JNI的功能與使用,可以閱讀Java Native Interface文檔https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html

同時,本文將介紹一些在可能在剛開始會注意不到的使用細節。

FindClass找不到類的問題

JNI類名由包名開始, 由'/'分隔,例如

”java/lang/String”

如果要查找的是一個數組類, 類名應為簽名形式,所以一個一維String數組的類定義為

[Ljava/lang/String;

可以參照https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp9502

但是目前即使全都傳入簽名形式的類名,FindClass依然會找到對應的類。原因是歷史遺留問題,參考https://bugs.openjdk.java.net/browse/JDK-6411605

為了保證正確性,可以在運行class文件時,加參數-Xcheck:jni可以校驗類名構造是否規范。

javah生成的函數名不正確的問題

在函數重載和內部類類型作為某個重載函數的參數時,會觸發javah生成的函數名不正確的問題,javah會按照JNI的名稱解析規則生成JNI函數名,但是JVM在運行時卻不會按照這個名字查找函數,因此會出現運行時找不到函數的情況。

參考https://bugs.openjdk.java.net/browse/JDK-8145897

package p;

class A {

  static class B {}

  static class C {

    native static long Foo(B bar);

  }

}

運行javah -jni -o jni_libA.h -classpath ./ p.A

預期的輸出是:

//Method: Foo

//Signature: (Lp/A$B;)J

JNIEXPORT jlong JNICALLJava_p_A_00024C_Foo__Lp_A_00024B_2

但實際會輸出:

//Method: Foo

//Signature: (Lp/A/B;)J

JNIEXPORT jlong JNICALLJava_p_A_00024C_Foo__Lp_A_B_2

內部類B的’$’被忽略。

可選的解決方法有兩種:

1.      不把有內部類作為參數的重載函數寫入本地方法

2.      在生成方法后手動添加’$’(‘00024’)

JNI中的異常機制

在有異常等待處理時不能調用大多數的JNI方法。要通過函數ExceptionCheck或ExceptionOccurred的返回值預期到有異常并返回,或處理并清除異常。

如果要獲得異常的描述,需要找到Throwable類,然后調用它的getMessage "()Ljava/lang/String;"方法,用GetStringUTFChars來獲取內容。

很多JNI方法會拋出異常,但有些異常不會被拋出,需要在應當拋出異常的地方添加條件判斷,用ThrowNew構造異常,最常見的是java.lang.ArithmeticException與 Java.lang.NullPointerException

JNI中原生數組的取值與賦值

如果想對數組進行寫入或讀出,Get<Type>ArrayElements和GetStringChars是非常有用的方式。

Get<PrimitiveType>ArrayElements系列函數允許返回一個指向實際元素的指針,或者分配一些內存來拷貝數據。 返回的原始數據的指針在調用釋放方法前是保證一直有效的,而且必須手動釋放每個獲取的數組。同時可以通過傳一個非空指針作為isCopy的參數來決定是否拷貝數據。

   jbyte* data = env->GetByteArrayElements(array, NULL);   

if (data != NULL) {

   memcpy(buffer, data, len);       

   env->ReleaseByteArrayElements(array, data, JNI_ABORT);   

}

上面的代碼是一個簡單的舉例,獲取了數組,然后拷貝了len長度的byte,最后釋放掉數組。

還有一個更簡單實現同樣功能的方式是

   env->GetByteArrayRegion(array, 0, len, buffer);

這種方式有幾個好處:

1.      只需要一個JNI調用,減少開銷.

2.      不需要對原始數據進行限制或者額外的拷貝數據

3.      減少在某些出錯后忘記釋放的風險

4.      會在越界時拋出異常

類似的,Set<Type>ArrayRegion系列方法是將數組中的元素賦值, GetStringRegion或者GetStringUTFRegion是獲得String中的字符。

通付盾SDK保護系統應用輸入為aar包,通過分析aar結構,將待保護的class文件轉換為AST(抽象語法樹),對AST進行同態翻譯,將其轉換為對應的本地代碼。本地化的轉換規則與AST節點數目一一對應。由于字節碼是托管代碼,運行于VM中(java代碼運行于JVM,安卓字節碼運行在Dalvik),對于操作VM內存模型,以及涉及VM特性的行為,如創建對象,拋出異常等操作,本地代碼無法表達對應的語義。對于帶有這樣語義的AST節點,本地代碼的翻譯遵循JNI調用規范,在確保本地化翻譯的正確性的同時兼顧了兼容性。

關于如何進行JNI的使用就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jni
AI

龙州县| 扎赉特旗| 页游| 庆云县| 墨脱县| 越西县| 台前县| 阳谷县| 高淳县| 日喀则市| 舞阳县| 邯郸县| 犍为县| 铜山县| 独山县| 青铜峡市| 金华市| 色达县| 阿坝| 涞源县| 繁峙县| 武陟县| 瓮安县| 河源市| 凤冈县| 建始县| 新宁县| 灌云县| 洛南县| 安顺市| 南汇区| 玉屏| 泗水县| 太湖县| 叶城县| 谢通门县| 衡东县| 资讯| 遵义县| 东乌珠穆沁旗| 山丹县|