20230711 12. 本地方法

本地方法

原則上說,“ 100% 純 Java ” 的解決方案是非常好的,但有時你也會想要編寫或使用其他語言的代碼(這種代碼通常稱爲 本地代碼

特別是在 Java 的早期階段,許多人都認爲使用 C++ 來加速 Java 應用中關鍵部分是個好主意。但是,實際上,這基本上是徒勞的。Java 平臺實現比網絡 I/O 要快得多,而網絡 I/O 是真正的瓶頸

求助於本地代碼是有缺陷的。如果應用的某個部分是用其他語言編寫的, 那麼就必須爲需要支持的每個平臺都提供一個單獨的本地類庫。用 C 或 C++ 編寫的代碼沒有對通過使用無效指針所造成的內存覆寫提供任何保護。編寫本地代碼很容易破壞你的程序,並感染操作系統

建議只有在必需的時候才使用本地代碼。特別是在以下 3 種情況下,也許應該使用本地代碼:

  • 你的應用需要訪問的系統特性和設備通過 Java 平臺是無法實現的
  • 你已經有了大量的測試過和調試過的用另一種語言編寫的代碼,並且知道如何將其導出到所有的目標平臺上
  • 通過基準測試,你發現所編寫的 Java 代碼比用其他語言編寫的等價代碼要慢得多

Java 平臺有一個用於和本地 C 代碼進行互操作的 API ,稱爲 Java 本地接口( JNI )

C++ 注意:你可以使用 C++ 代替 C 來編寫本地方法。這樣會有一些好處:類型檢查會更嚴格一些,訪問 JNI 函數會更便捷一些。然而,JNI 並不支持 Java 類和 C++ 類之間的任何映射機制

從 Java 程序中調用 C 函數

Java 編程語言使用關鍵字 native 表示本地方法

class HelloNative {
    public static native void greeting();
}

本地方法既可以是靜態的也可以是非靜態的

爲了實現本地代碼,需要編寫一個相應的 C 函數,你必須完全按照 Java 虛擬機預期的那樣來命名這個函數。其規則是:

  1. 使用完整的 Java 方法名,比如: HelloNative.greeting 。如果該類屬於某個包,那麼在前面添加包名,比如: v2ch12.helloNative.HelloNative.greeting
  2. 用下劃線替換掉所有的句號,並加上 Java_ 前綴,例如, Java_v2ch12_helloNative_HelloNative_greeting
  3. 如果類名含有非 ASCII 字母或數字,如: _$ 或是大於 \u007F 的 Unicode 字符,用 _0xxxx 來替代它們, xxxx 是該字符的 Unicode 值的 4 個十六進制數序列
PS D:\Develop\workspace\study\study-corejava\src\main\java> javac v2ch12/helloNative/HelloNative.java
PS D:\Develop\workspace\study\study-corejava\src\main\java> javah v2ch12.helloNative.HelloNative

生成文件 D:\Develop\workspace\study\study-corejava\src\main\java\v2ch12_helloNative_HelloNative.h

將函數原型從頭文件中複製到源文件中,並且給出函數的實現代碼:

#include "HelloNative.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_v2ch12_helloNative_HelloNative_greeting(JNIEnv* env, jclass cl)
{  
   printf("Hello Native World!\n");
}

其他

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章