要在java中呼叫c語言的庫,需要使用Java提供了JNI。
舉例說明
在c語言中定義一個 void sayHello()函式(列印Hello World);然後在Java中呼叫這個函式顯示Hello Word.
現在分別從Java和C語言兩部分說明:
1. Java 部分
首先定義一個HelloNative,在其中申明sayHello函式,函式要申明為Native 型別的.如下:
public class HelloNative {
public native void sayHello();
}
編譯這個類,生成class檔案:
javac HelloWorld.java
利用javah生成需要的h檔案
javah HelloNative
生成的 h檔案大概如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class HelloNative */
#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloNative
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloNative_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
可以看一下上面自動生成的程式,程式include了jni.h,這個標頭檔在 $JAVA_HOME下的include資料夾下. 還可以發現生成的函式名是在之前的函式名前面加上了Java_HelloNative。
2. C語言部分
根據上面生成的h檔案撰寫相應的程式碼實現,建立一個 HelloNative.cpp用來實現顯示Hello World的函式.如下:
#include
#include "HelloNative.h"
JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *, jobject)
{
printf("Hello World!
");
}
程式碼撰寫完成之後,我們再用gcc編譯成庫檔案,命令如下;
gcc -fPIC -I/usr/lib/jvm/java-7-openjdk-i386/include -I/usr/lib/jvm/java-7-openjdk-i386/include/linux -shared -o libHelloNative.so HelloNative.cpp
這樣就會在當前目錄下生成一個libHelloNative.so的庫檔案.這時需要的庫已經生成,在C語言下的工作已經完成了.
接下來需要在Java中撰寫一個程式測試一下.在程式前,需要將我們的庫載入進去.載入的方法是呼叫Java的 System.loadLibrary("HelloNative");
public class TestNative
{
static {
try {
System.loadLibrary("HelloNative");
}
catch(UnsatisfiedLinkError e) {
System.out.println( "Cannot load hello library:
" + e.toString() );
}
}
public static void main(String[] args) {
HelloNative test = new HelloNative();
test.sayHello();
}
}
但是再編譯後,執行的時候,問題又出現了.
Cannot load hello library:
java.lang.UnsatisfiedLinkError: no HelloNative in java.library.path
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloNative.sayHello()V
at HelloNative.sayHello(Native Method)
at TestNative.main(TestNative.java:13)
載入庫失敗,但是庫明明就是放在當前資料夾下的,怎麼會載入失敗呢?
用System.getProperty("java.library.path")檢視,發現java.library.path中並不u存在當前的目錄.主要有以下的幾個解決辦法:
1) 將生成的庫複製到java.library.path有的路徑中去,當然這樣不是很好
2) 設定環境變數export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ,將當前的目錄加入到LD_LIBRARY_PATH中
3) 設定java 的選項,將當前的目錄加入到其中 .java -Djava.library.path=. $LD_LIBRARY_PATH
這樣之後程式就能夠成功的執行了.可以看見顯示的"Hello World!"了