jni是java native interface的縮寫,中文為java本地調用。從java1.1開始,java native interface(jni)标準成為平台的一部分,它允許java代碼和其他語言寫的代碼進行互動。jni一開始是為了本地已編譯語言,尤其是c和c++而設計的,但是它并不妨礙你使用其他語言,隻要調用約定受支援就可以了。
使用與本地已編譯的代碼互動,通常會喪失平台可移植性。但是,有些情況這樣做是可以接受的,甚至是必須的。例如,使用一些舊的庫,與硬體、進行互動,或者為了提高程式的性能。jni标準至少保證能工作在任何java 實作下。
标準的類庫可能不支援你的程式所需的特性。或許你已經有了一個用其他語言寫成的庫或程式,而你希望在程式中使用它。
你可能需要用底層語言實作一個小型的時間敏感代碼,比如彙編,然後在你的程式中調用這些功能。
以下是具體步驟:
編寫帶有native聲明的方法的類
·使用指令編譯所編寫的java類,然後使用javah + java類名生成擴充名為h的頭檔案
·使用c/c++實作本地方法
·将c/c++編寫的檔案生成
·完成
示例:
helloworld.java:
package com.magc.jni;
public class helloworld {
static {
system.loadlibrary("hello");
}
public native void displayhello();
/**
* @param args
*/
public static void main(string[] args) {
new helloworld().displayhello();
}
進入src目錄下,編譯該java類,
指令:javac ./com/magc/jni/helloworld.java
在該helloworld.java所在目錄下生成helloworld.class
然後使用javah生成頭檔案,
指令:javah -jni com.magc.jni.helloworld
在目前目錄下生成com_magc_jni_helloworld.h頭檔案,此檔案供c、c++程式來引用并實作其中的函數
helloworld.h:
/* do not edit this file - it is machine generated */
#include <jni.h>
/* header for class com_magc_jni_helloworld */
#ifndef _included_com_magc_jni_helloworld
#define _included_com_magc_jni_helloworld
#ifdef __cplusplus
extern "c" {
#endif
/*
* class: com_magc_jni_helloworld
* method: displayhello
* signature: ()v
*/
jniexport void jnicall java_com_magc_jni_helloworld_displayhello
(jnienv *, jobject);
注:1)、此頭檔案是不需要使用者編譯的,直接供其它c、c++程式引用。
2)、此頭檔案中的java_com_magc_jni_helloworld_displayhello(jnienv *, jobject)方法,是将來與動态連結庫互動的接口,并需要名字保持一緻。
jni_helloworldimpl.cpp:
#include "com_magc_jni_helloworld.h"
#include <stdio.h>
(jnienv *env, jobject obj)
{
printf("from jni_helloworldimpl.cpp :");
printf("hello world ! \n");
return;
此c++檔案實作了上述頭檔案中的函數,注意方法函數名要保持一緻。
編譯生成動态庫libhello.so,
總結了一下,jni一般有以下一些應用場景
1.高性能 ,在一些情況下因為處理運算量非常大,為了擷取高性能,直接使用java是不能勝任的,如:一些圖形的處理
2.調用一些硬體的驅動或者一些軟體的驅動,比如調用一些外部系統接口的驅動,如:讀卡器的驅動,oci驅動
3.需要使用大記憶體,遠遠超過jvm所能配置設定的記憶體,如:程序内cache
4.調用c或者作業系統提供的服務,如:java調用搜尋服務,其中搜尋是由c/c++實作的,不過這個一般可以設計成更加通用的方式,比如soa的方式
所有這些場景的前提是犧牲了java代碼的可移植性,不同的os,甚至版本都需要寫不同版本的native實作
經測試jni實作方法比普通java方法快13~15倍。
參考:
如有問題請留言,轉載注明出處。