JNI簡介
JNI是Java Native Interface的縮寫,中文爲Java本地接口。使用此種方式,可以對C/C++代碼進行調用,但是,其在本質上是對C/C++生成的動態庫進行調用而不是直接對C/C++代碼進行調用。從Java1.1開始,Java Native Interface(JNI)標準成爲java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI一開始是爲了本地已編譯語言,尤其是C和C++而設計的,但是它並不妨礙你使用其他語言,只要調用約定受支持就可以了。
使用java與本地已編譯的代碼交互,通常會喪失平臺可移植性。但是,有些情況下這樣做是可以接受的,甚至是必須的,比如,使用一些舊的庫,與硬件、操作系統進行交互,或者爲了提高程序的性能。JNI標準至少保證本地代碼能工作在任何Java 虛擬機實現下。
JNI其實是JAVA和其他編程語言代碼的橋樑,通過JNI,兩種代碼之間可以進行無障礙的對接。從下圖的結構中,可以清晰知道JAVA、JNI和其他語言之間的關係。
JNI編程實例
(2)使用javac命令編譯所編寫的java類 (操作命令如:javac TestJni.java)
(3)使用javah命令生成擴展名爲.h的頭文件 (操作命令如:javah TestJni)
注意:進行生成頭文件時候不要在文件名後面加上後綴
(4)使用C/C++實現JAVA本地方法
(5)將C/C++編寫的文件,生成動態連接庫(.so後綴文件)
(6)OK
public class TestJni
{
public native void show();
static
{
//本處使用的是System.load(),所以使用的是絕對路徑。而System.loadLibrary()使用的是java.library.ptah路徑,且不帶後綴和lib前綴
System.load("/home/zdh/c_test/TestJni/libTestJni.so");
//System.loadLibrary("TestJni");
}
public static void main(String args[])
{
TestJni obj = new TestJni();
System.out.println("======1======");
obj.show();
System.out.println("======2======");
}
}
注意:本處的java程序並沒有引入package。目的是減少CLASSPATH對理解JNI的干擾。
進入TestJni文件夾,輸入命令javac TestJni.java,對java文件進行編譯。如果java文件沒有錯誤,會在TestJni目錄中生成TestJni.class字節碼文件。
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class TestJni */ #ifndef _Included_TestJni #define _Included_TestJni #ifdef __cplusplus extern "C" { #endif /* * Class: TestJni * Method: show * Signature: ()V */ JNIEXPORT void JNICALL Java_TestJni_show (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
頭文件中聲明瞭JNIEXPORT void JNICALL Java_TestJni_show(JNIEnv *, jobject);
#include "TestJni.h" //這個頭文件是javah生成的頭文件,在這裏將它包含進來
#include "stdio.h"
#include "string.h"
JNIEXPORT void JNICALL Java_TestJni_show(JNIEnv *, jobject)
{
printf("=====hzdeng jni======\n");
}
這個C++代碼中僅實現了一個接口,接口中只進行了一個操作,即打印“=====hzdeng jni======”這一行信息。第五步:將C/C++編寫的文件,生成動態連接庫
=====hzdeng jni======
======2======
常見問題:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no libTestJni in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1698)
at java.lang.Runtime.loadLibrary0(Runtime.java:840)
at java.lang.System.loadLibrary(System.java:1047)
at TestJni.<clinit>(TestJni.java:9)
此打印是說明,程序在java.library.path指定的路徑下,沒有找到相應的動態庫文件。export LD_LIBRARY_PATH
=====hzdeng jni======
======2======