java jni呼叫c/c++的so動態連結庫簡易demo
需求:
工作中需要多個團隊協作開發,而不同團隊提供的程式語言不同,比較常見的是底層互動使用C++或c來實現任務排程,java層實現業務排程或者業務實現,正好有涉及到這方面的應用,就分享一下java使用jni呼叫linux中so檔案的幾個注意事項
編寫簡易的demo:
1: java程式碼編寫jni定義的類Hello.java
package com.jni;
public class Hello{
static{
System.load("/home/admin/lib/libHello.so");
}
public native void say();
public native String world(String str);
public static void main(String...args){
Hello hello = new Hello();
hello.say();
System.out.println("java : "+hello.world("hello"));
}
}
2:編譯Hello.java - Hello.class
javac -d . Hello.java
會得到 com/jni/Hello.class
3: 編譯Hello.class 生成 com_jni_Hello.h 的標頭檔案
javah com.jni.Hello
4: 編寫c++/c的業務程式碼,引用com_jni_Hello.h 的標頭檔案,並實現定義的方法
c程式碼: Hello.c
#include "com_jni_Hello.h"
#include "string.h"
JNIEXPORT void JNICALL Java_com_jni_Hello_say(JNIEnv *env, jobject object){
printf("hello world!");
}
JNIEXPORT jstring JNICALL Java_com_jni_Hello_world(JNIEnv *env, jobject obejct, jstring string){
const char *wd = " world!!";
const char *getstr = (*env)->GetStringUTFChars(env,string, 0);
char *str;
str=strcpy(str,wd);
str=strcpy(str,getstr);
jstring out= (*env)->NewStringUTF(env,str);
return out;}
c++程式碼:Hello.cpp
#include "com_jni_Hello.h"
#include "string.h"
JNIEXPORT void JNICALL Java_com_jni_Hello_say(JNIEnv *env, jobject object){
printf("hello world!");
}
JNIEXPORT jstring JNICALL Java_com_jni_Hello_world(JNIEnv *env, jobject obejct, jstring string){
const char *wd = " world!!";
const char *getstr = env->GetStringUTFChars(string,JNI_FALSE);
char *str;
str=strcpy(str,wd);
str=strcpy(str,getstr);
jstring out= env->NewStringUTF(str);
return out;
}
5:編譯c/c++ 程式碼生成動態連結庫 .so檔案
c編譯: -o
gcc -fPIC -D_REENTRANT -I/home/admin/install/jdk1.8.0_131/include -I/home/admin/install/jdk1.8.0_131/include/linux -c Hello.c
注意:第一個 -I 是jni.h 第二個是jni_md.h
-so
gcc -shared -o libHello.so Hello.o
c++:編譯:
g++ Hello.cpp -fPIC -D_REENTRANT -I/home/admin/install/jdk1.8.0_131/include -I/home/admin/install/jdk1.8.0_131/include/linux -shared -o libHello.so
6:把so的路勁新增到LD_LIBRARY_PATH變數
export LD_LIBRARY_PATH=/home/admin/lib
7: 執行java程式
java com.jni.Hello
8:結果
java : hello
hello world!
------注意
1:jna是基於jni的封裝,要求執行速度而言建議使用jni,但是要求開發效率而言可以直接使用jna,直接免去編譯標頭檔案和載入c/c++載入標頭檔案這兩步;
2:所有jni定義的方法都需要加入JNIEnv變數;
3:對於c++而言,新的標準庫沒有了.h的概念
對於c而言沒有名稱空間的概念