1. 程式人生 > >java jni呼叫c/c++的so動態連結庫簡易demo

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而言沒有名稱空間的概念