Java jvm級別native關鍵詞、JNI詳解
1.native關鍵詞的引入
再完美的程式語言也有自己的不足之處,當然Java也不例外,Java的不足之處除了體現在執行速度(這點往往被一些其他程式語言使用者所詬病)上要比傳統的C++慢許多之外,Java無法直接訪問到作業系統底層(如系統硬體等),為此Java使用native(原生的)關鍵詞來擴充套件Java程式的功能。native關鍵字說明其修飾的方法是一個原生態方法,方法對應的實現不是在當前檔案,而是在用其他語言(如C和C++)實現的檔案中。Java語言本身不能對作業系統底層進行訪問和操作,但是可以通過JNI介面呼叫其他語言來實現對底層的訪問。JNI是Java Native Interface的縮寫,它提供了若干的API實現了Java和其他語言的通訊(主要C&C++)。從Java1.1開始,JNI標準成為java平臺的一部分,它允許Java程式碼和其他語言寫的程式碼進行互動。JNI一開始是為了本地已編譯語言,尤其是C和C++而設計的,但是它並不妨礙你使用其他程式語言,只要呼叫約定受支援就可以了。使用java與本地已編譯的程式碼互動,通常會喪失平臺可移植性。但是,有些情況下這樣做是可以接受的,甚至是必須的。例如,使用一些舊的庫,與硬體、作業系統進行互動,或者為了提高程式的效能。JNI標準至少要保證原生程式碼能工作在任何Java 虛擬環境。簡而言之,JNI功能即為:Java和原生程式碼間的雙向互動。JNI允許Java程式碼使用以其他語言編寫的程式碼和程式碼庫。Invocation API(JNI的一部分)可以用來將Java虛擬機器(JVM)嵌入到本機應用程式中,從而允許程式設計師從本機程式碼內部呼叫Java程式碼。
2.JNI的使用場合
1、JAVA程式和本地程式使用TCP/IP或者IPC進行互動。
2、當用JAVA程式連線本地資料庫時,使用JDBC提供的API。
3、JAVA程式可以使用分散式物件技術,如JAVA IDL API。
這些方案的共同點是,JAVA和C處於不同的執行緒,或者不同的機器上。這樣,當本地程式崩潰時,不會影響到JAVA程式。
下面這些場合中,同一程式內JNI的使用無法避免:
1、程式當中用到了JAVA API不提供的特殊系統環境才會有的特徵。而跨程式操作又不現實。
2、可能想訪問一些己有的本地庫,但又不想付出跨程式呼叫時的代價,如效率,記憶體,資料傳遞方面。
3、JAVA程式當中的一部分程式碼對效率要求非常高,如演算法計算,圖形渲染等。
總之,只有當必須在同一程式中呼叫原生程式碼時,再使用JNI。
3.JNI的書寫步驟
第一步:編寫帶有native宣告的方法的Java類
第二步:使用javac命令編譯編寫的Java類
第三步:使用java -jni 來生成字尾名為.h的標頭檔案
第四步:使用其他語言(C、C++)實現本地方法
第五步:將本地方法編寫的檔案生成動態連結庫
第六步:執行程式
4.一個JNI的簡單應用例子(以HelloJNI為例子)
第一步:編寫帶有native宣告的方法的Java類public class HelloJNI {
public native void displayHelloJNI();//所有native關鍵詞修飾的都是對本地的宣告
static {
System.loadLibrary("hello");//載入本地庫
}
public static void main(String[] args) {
new JNI().displayHelloJNI();
}
}
宣告native方法:如果想將一個方法做為一個本地方法的話,那麼就必須宣告該方法為native,並且不能實現。 Load動態庫:System.loadLibrary(“hello”);載入動態庫(可以這樣理解:方法 displayHelloJNI()沒有實現,但是在後續步驟中就直接使用了,所以必須在使用之前對它進行初始化),這裡一般是以static塊進行載入的。同時需要注意的是System.loadLibrary()的引數“hello”是動態庫的名字。
第二步:使用javac命令編譯編寫的Java類
javac HelloJNI.java
注意:JDK環境變數的配置
第三步:使用java -jni 來生成字尾名為.h的標頭檔案( 生成副檔名為h的標頭檔案javah HelloJNI)
標頭檔案javah HelloJNI內容如下:
/*DO NOT EDI TTHIS FILE - it is mach inegenerated*/
#include<jni.h>
/*Header for class HelloJNI*/
#ifndef_Included_HelloJNI
#define_Included_HelloJNI
#ifdef__cplusplus
extern"C"{
#endif
/*
*Class:HelloJNI
*Method:displayHelloJNI
*Signature:()V
*/
JNIEXPORTvoidJNICALL
Java_HelloJNI_displayHelloJNI(JNIEnv*,jobject);
#ifdef__cplusplus
}
#endif
#endif
注意:這個h檔案相當於在java裡面的介面,這裡宣告瞭一個Java_HelloJNI_displayHelloJNI (JNIEnv *, jobject)方法,然後在本地方法裡面實現這個方法,也就是說在編寫C/C++程式的時候所使用的方法名必須和這裡的一致
第四步:使用其他語言(C、C++)實現本地方法(編寫本地方法實現和由javah命令生成的標頭檔案裡面宣告的方法名相同的方法)
#include"jni.h"
#include"HelloJNI.h"
//#includeotherheaders
JNIEXPORT void JNICALL
Java_HelloJNI_displayHelloJNI(JNIEnv*env,jobject obj)
{
printf("HelloJNI!\n");
return;
}
注意:程式碼第一行需要將jni.h(該檔案可以在%JAVA_HOME%/include資料夾下面找到)檔案引入,因為在程式中的JNIEnv、 jobject等型別都是在該標頭檔案中定義的;另外在第2行需要將HelloJNI.h標頭檔案引入,然後儲存為 HelloJNIImpl.c。
第五步:將本地方法編寫的檔案生成動態連結庫
這裡以在Windows中為例,需要生成dll檔案。在儲存HelloWorldJNI.c資料夾下面,使用VC的編輯器cl為:cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloJNIImp.c -Fehello.dll 注意:生成的dll檔名在選項-Fe後面配置,這裡是hello,因為在HelloJNI.java檔案中我們loadLibary的時候使用的名字是hello。當然這裡修改之後那裡也需要修改。另外需要將-I%java_home%\include -I%java_home%\include\win32引數加上,因為在第四步裡面編寫本地方法的時候引入了jni.h檔案。
如果配置了MinGW,也可以這樣來編譯:gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,–kill-at -Id:/java/include –Id:/java/include/win32 -shared -o (輸出的dll檔名,如sum.dll) (輸入的c/c++原始檔,如abc.c)。
第六步:執行程式
執行javaHelloJNI;如果用eclipse/myeclipse,需將dll或so檔案放在專案下,而不是src及其子目錄下;如果用命令列編譯,把dll檔案放在該包的同目錄下。
相關文章
- 【詳解】JNI (Java Native Interface) (二)Java
- 【詳解】JNI (Java Native Interface) (三)Java
- 【詳解】JNI (Java Native Interface) (四)Java
- 【詳解】JNI(Java Native Interface)(一)Java
- Java關鍵詞synchronized解讀Javasynchronized
- Java native關鍵字Java
- C#9新關鍵詞詳解C#
- java—— finall 關鍵詞Java
- HanLP 關鍵詞提取演算法分析詳解HanLP演算法
- 關鍵詞加粗和插入關鍵詞
- 【GiraKoo】Java Native Interface(JNI)的空間(引用)管理Java
- Java的關鍵詞和註釋符Java
- Java 10 var關鍵字詳解和示例教程Java
- robot 關鍵詞
- 關鍵詞提取
- 匹配關鍵詞和敏感詞
- 詳解 React NativeReact Native
- 詳解Vue NativeVue
- 網站關鍵詞堆砌後,處理關鍵詞堆砌方法網站
- NLP標籤/關鍵詞-提取工具-java開發Java
- Java註解最全詳解(超級詳細)Java
- 什麼是長尾關鍵詞?如何找到長尾關鍵詞?
- 高亮:單關鍵詞、多關鍵詞、多組多關鍵詞,從簡單到複雜實現滿足多方面需求的頁面關鍵詞高亮
- JNI-從jvm原始碼分析Thread.interrupt的系統級別執行緒打斷原理JVM原始碼thread執行緒
- 什麼是關鍵詞策略?網站關鍵詞佈局重要嗎?網站
- 如何優化多個關鍵詞?分享多關鍵詞優化心得優化
- Go 切片詳解(理解是關鍵)Go
- C++ typeid關鍵字詳解C++
- 作用域鏈this關鍵詞
- Eclipse註釋關鍵詞Eclipse
- 關鍵詞感知檢索
- transient關鍵詞的概述
- JVM效能調優的6大步驟,及關鍵調優引數詳解JVM
- JVM(二)Java虛擬機器組成詳解JVMJava虛擬機
- c# yield關鍵字原理詳解C#
- C語言中static關鍵字詳解C語言
- Pig 實現關鍵詞匹配
- java:識別符號 關鍵字 變數Java符號變數