JNI(Java Native Interface)是指Java平臺和本地C代碼進行相互操作的API接口,稱為Java本地代碼接口。當Java程序需要訪問系統的各個特性和設備時,或者一些要求效率和速度的場合時,此時應該采用JNI調用本地C或C++代碼,來完成。如下圖所示:
圖一 JNI模型圖
關于JNI函數的注冊可以分為靜態注冊和動態注冊。本文主要講解靜態注冊之Java調用C語言,具體步驟如圖二所示:
1)在java類中使用native聲明一個本地方法,使用javac命令編譯java類
2)運行javah獲得頭文件,包括這個本地方法的聲明格式
3)用C實現本地方法
4)生成.so文件,并將其放入到共享類庫中
5)在java文件中加載該類庫,調用本地方法。
圖二 JNI開發步驟圖
具體實例演示如下所示:
(一) 首先創建MyJNI.java類,在本類中使用native生命一個方法cSayHello(),代碼如下所示:
package com.farsight.demo;
public class MyJNI
{
public static native void cSayHello();
}
在Linux環境下,進入到java類所在目錄,例如MyJNI.java存儲在Desktop目錄里,執行命令如下:
編譯MyJNI.java文件,執行之后在Desktop目錄里可以看到文件夾com/farsight/demo里的MyJNI.class文件。執行命令如下:
(二) 執行javah命令,生成.h文件。執行命令如下:
執行之后,可以看到在Desktop目錄下新生成的com_farsight_demo_MyJNI.h文件,該文件中自動生成,無需修改。代碼中JNIEXPORT后面就是我們在C語言里需要實現的方法。代碼如下所示:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_farsight_demo_MyJNI */
#ifndef _Included_com_farsight_demo_MyJNI
#define _Included_com_farsight_demo_MyJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_farsight_demo_MyJNI
* Method: cSayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_farsight_demo_MyJNI_cSayHello
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
(三) 用C實現本地方法,在方法中輸出一句話。MyJNI.c代碼如下:
#include "com_farsight_demo_MyJNI.h"
#include <jni.h>
#include <stdio.h>
J NIEXPORT void JNICALL Java_com_farsight_demo_MyJNI_cSayHello(JNIEnv * env ,jclass cl)
{
printf("hello in c called by java");
}
(四) 生成.so文件,并將其放入到共享類庫中。執行之后可以看到新生成的libMyJNI.so文件。執行代碼如下:
(五) 在java測試文件中加載該類庫,調用本地方法。MyJNITest.java代碼如下:
import com.farsight.demo.MyJNI;
public class MyJNITest
{
public static void main(String args[])
{
MyJNI.cSayHello();
}
static
{
System.loadLibrary("MyJNI");
}
}
編譯并運行MyJNITest.java文件,執行之后可以看到在MyJNI.c文件中輸出的一句話。執行代碼如下所示: