成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java JNI深度分析與實踐

開發 后端
Java JNI是Java Native Interface的縮寫,中文可譯為Java本地調用。Java Native Interface (JNI)標準成為java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。本文向您詳細介紹Java JNI。

Java 環境和語言對于應用程序開發來說是非常安全和高效的。但是,一些應用程序卻需要執行純 Java 程序無法完成的一些任務,比如:

與舊有代碼集成,避免重新編寫。

實現可用類庫中所缺少的功能。舉例來說,在 Java 語言中實現 ping 時,您可能需要 Internet Control Message Protocol (ICMP) 功能,但基本類庫并未提供它。

***與使用 C/C++ 編寫的代碼集成,以充分發掘性能或其他與環境相關的系統特性。

解決需要非 Java 代碼的特殊情況。舉例來說,核心類庫的實現可能需要跨包調用或者需要繞過其他 Java 安全性檢查。

JNI 允許您完成這些任務。它明確分開了 Java 代碼與本機代碼(C/C++)的執行,定義了一個清晰的 API 在這兩者之間進行通信。從很大程度上說,它避免了本機代碼對 JVM 的直接內存引用,從而確保本機代碼只需編寫一次,并且可以跨不同的 JVM 實現或版本運行。

借助 JNI,本機代碼可以隨意與 Java 對象交互,獲取和設計字段值,以及調用方法,而不會像 Java 代碼中的相同功能那樣受到諸多限制。這種自由是一把雙刃劍:它犧牲 Java 代碼的安全性,換取了完成上述所列任務的能力。在您的應用程序中使用 JNI 提供了強大的、對機器資源(內存、I/O 等)的低級訪問,因此您不會像普通 Java 開發人員那樣受到安全網的保護。JNI 的靈活性和強大性帶來了一些編程實踐上的風險,比如導致性能較差、出現 bug 甚至程序崩潰。您必須格外留意應用程序中的代碼,并使用良好的實踐來保障應用程序的總體完整性。

本文介紹 JNI 用戶最常遇到的 10 大編碼和設計錯誤。其目標是幫助您認識到并避免它們,以便您可以編寫安全、高效、性能出眾的 JNI 代碼。本文還將介紹一些用于在新代碼或已有代碼中查找這些問題的工具和技巧,并展示如何有效地應用它們。

Java JNI 編程缺陷可以分為兩類

性能:代碼能執行所設計的功能,但運行緩慢或者以某種形式拖慢整個程序。

正確性:代碼有時能正常運行,但不能可靠地提供所需的功能;最壞的情況是造成程序崩潰或掛起。

性能缺陷

程序員在使用 JNI 時的 5 大性能缺陷如下:

◆不緩存方法 ID、字段 ID 和類

◆觸發數組副本

◆回訪(Reaching back)而不是傳遞參數

◆錯誤認定本機代碼與 Java 代碼之間的界限

◆使用大量本地引用,而未通知 JVM

◆不緩存方法 ID、字段 ID 和類

要訪問 Java 對象的字段并調用它們的方法,本機代碼必須調用 FindClass()、GetFieldID()、GetMethodId() 和 GetStaticMethodID()。對于 GetFieldID()、GetMethodID() 和 GetStaticMethodID(),為特定類返回的 ID 不會在 JVM 進程的生存期內發生變化。但是,獲取字段或方法的調用有時會需要在 JVM 中完成大量工作,因為字段和方法可能是從超類中繼承而來的,這會讓 JVM 向上遍歷類層次結構來找到它們。由于 ID 對于特定類是相同的,因此您只需要查找一次,然后便可重復使用。同樣,查找類對象的開銷也很大,因此也應該緩存它們。

舉例來說,清單 1 展示了調用靜態方法所需的 JNI 代碼:

清單 1. 使用 JNI 調用靜態方法

  1.    int val=1;   
  2.   jmethodID method;   
  3.   jclass cls;   
  4.   cls = (*env)->FindClass(env, "com/ibm/example/TestClass");   
  5.   if ((*env)->ExceptionCheck(env)) {   
  6.   return ERR_FIND_CLASS_FAILED;   
  7.   }   
  8.   method = (*env)->GetStaticMethodID(env, cls, "setInfo", "(I)V");   
  9.   if ((*env)->ExceptionCheck(env)) {   
  10.   return ERR_GET_STATIC_METHOD_FAILED;   
  11.   }   
  12.   (*env)->CallStaticVoidMethod(env, cls, method,val);   
  13.   if ((*env)->ExceptionCheck(env)) {   
  14.   return ERR_CALL_STATIC_METHOD_FAILED;   
  15.   } 

當我們每次希望調用方法時查找類和方法 ID 都會產生六個本機調用,而不是***次緩存類和方法 ID 時需要的兩個調用。

緩存會對您應用程序的運行時造成顯著的影響。考慮下面兩個版本的方法,它們的作用是相同的。清單 2 使用了緩存的字段 ID:

清單 2. 使用緩存的字段 ID

  1.      int sumValues2(JNIEnv* env, jobject obj, jobject allValues){   
  2.   jint avalue = (*env)->GetIntField(env, allValues, a);   
  3.   jint bvalue = (*env)->GetIntField(env, allValues, b);   
  4.   jint cvalue = (*env)->GetIntField(env, allValues, c);   
  5.   jint dvalue = (*env)->GetIntField(env, allValues, d);   
  6.   jint evalue = (*env)->GetIntField(env, allValues, e);   
  7.   jint fvalue = (*env)->GetIntField(env, allValues, f);   
  8.   return avalue + bvalue + cvalue + dvalue + evalue + fvalue;   
  9.   } 

清單 3. 未緩存字段 ID

  1.    int sumValues2(JNIEnv* env, jobject obj, jobject allValues){   
  2.   jclass cls = (*env)->GetObjectClass(env,allValues);   
  3.   jfieldID a = (*env)->GetFieldID(env, cls, "a", "I");   
  4.   jfieldID b = (*env)->GetFieldID(env, cls, "b", "I");   
  5.   jfieldID c = (*env)->GetFieldID(env, cls, "c", "I");   
  6.   jfieldID d = (*env)->GetFieldID(env, cls, "d", "I");   
  7.   jfieldID e = (*env)->GetFieldID(env, cls, "e", "I");   
  8.   jfieldID f = (*env)->GetFieldID(env, cls, "f", "I");   
  9.   jint avalue = (*env)->GetIntField(env, allValues, a);   
  10.   jint bvalue = (*env)->GetIntField(env, allValues, b);   
  11.   jint cvalue = (*env)->GetIntField(env, allValues, c);   
  12.   jint dvalue = (*env)->GetIntField(env, allValues, d);   
  13.   jint evalue = (*env)->GetIntField(env, allValues, e);   
  14.   jint fvalue = (*env)->GetIntField(env, allValues, f);   
  15.   return avalue + bvalue + cvalue + dvalue + evalue + fvalue 

清單 2 用 3,572 ms 運行了 10,000,000 次。清單 3 用了 86,217 ms — 多花了 24 倍的時間。

觸發數組副本

JNI 在 Java 代碼和本機代碼之間提供了一個干凈的接口。為了維持這種分離,數組將作為不透明的句柄傳遞,并且本機代碼必須回調 JVM 以便使用 set 和 get 調用操作數組元素。Java 規范讓 JVM 實現決定讓這些調用提供對數組的直接訪問,還是返回一個數組副本。舉例來說,當數組經過優化而不需要連續存儲時,JVM 可以返回一個副本。(參見 參考資料 獲取關于 JVM 的信息)。

隨后,這些調用可以復制被操作的元素。舉例來說,如果您對含有 1,000 個元素的數組調用 GetLongArrayElements(),則會造成至少分配或復制 8,000 字節的數據(每個 long 1,000 元素 * 8 字節)。當您隨后使用 ReleaseLongArrayElements() 更新數組的內容時,需要另外復制 8,000 字節的數據來更新數組。即使您使用較新的 GetPrimitiveArrayCritical(),規范仍然準許 JVM 創建完整數組的副本。

GetTypeArrayRegion() 和 SetTypeArrayRegion() 方法允許您獲取和更新數組的一部分,而不是整個數組。通過使用這些方法訪問較大的數組,您可以確保只復制本機代碼將要實際使用的數組部分。

舉例來說,考慮相同方法的兩個版本,如清單 4 所示:

清單 4. 相同方法的兩個版本

  1.  jlong getElement(JNIEnv* env, jobject obj, jlongArray arr_j,   
  2.   int element){   
  3.   jboolean isCopy;   
  4.   jlong result;   
  5.   jlong* buffer_j = (*env)->GetLongArrayElements(env, arr_j, &isCopy);   
  6.   result = buffer_j[element];   
  7.   (*env)->ReleaseLongArrayElements(env, arr_j, buffer_j, 0);   
  8.   return result;   
  9.   }   
  10.   jlong getElement2(JNIEnv* env, jobject obj, jlongArray arr_j,   
  11.   int element){   
  12.   jlong result;   
  13.   (*env)->GetLongArrayRegion(env, arr_j, element,1, &result);   
  14.   return result;   
  15.   }   
  16.   } 

 

【編輯推薦】

  1. Java通過JNI調用C語言的方法
  2. Java: JNI完全手冊
  3. 探秘Java 7:JVM動態語言支持詳解
  4. JScript、Java、JavaScript和JSP總結
  5. Java JDBC編程總結
責任編輯:佚名 來源: 網絡轉載
相關推薦

2011-06-16 08:43:39

JAVAJIN

2024-12-24 14:01:10

2025-03-27 04:10:00

2024-09-19 08:49:13

2024-08-30 09:53:17

Java 8編程集成

2023-12-04 16:18:30

2024-10-10 08:26:30

2009-07-24 13:54:39

MVVM模式

2018-03-14 08:10:44

深度學習

2023-05-08 12:03:14

Linux內核進程

2024-07-08 07:30:47

2022-07-08 09:26:45

Flink快手計算

2025-05-12 01:33:00

異步函數Promise

2009-09-03 11:47:43

Groovy與Java

2022-12-21 08:32:34

OLAPDruid架構

2017-06-16 09:39:32

優酷實踐阿里云

2025-03-25 10:29:52

2024-11-13 08:47:24

2011-03-01 09:23:47

移動Web應用開發成本
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产午夜高清 | 狠狠干av | 大乳boobs巨大吃奶挤奶 | 亚洲精品91| 情侣av | 亚洲精品久久久蜜桃 | 国产精品国产精品国产专区不片 | 久久狠狠| 欧美亚洲国产精品 | 日韩一区在线播放 | 日本黄色免费视频 | 男女在线免费观看 | 久草网视频 | 久草青青 | 日韩精品一区二区三区高清免费 | 国产亚洲二区 | 国产xxxx岁13xxxxhd | 欧美黑人体内she精在线观看 | 五月婷婷在线视频 | 亚洲欧洲精品在线 | 不卡在线视频 | 成人国产精品入口免费视频 | 久久99精品久久久久久 | 日本 欧美 三级 高清 视频 | 91麻豆精品国产91久久久久久 | 91在线播 | 日本欧美在线观看视频 | 欧美三级在线 | 亚洲欧洲精品在线 | 在线观看中文字幕视频 | 亚洲狠狠丁香婷婷综合久久久 | www.久久久久久久久久久久 | 国产免费一区二区 | 精品一区二区不卡 | 少妇av片 | 中文字幕在线观看一区二区 | 欧美操操操 | 综合二区| 国产中文字幕在线观看 | 国产1区2区3区 | 国产精品黄视频 |