JAVA JNI 調用C/C++庫提高運行效率 (圖)

JAVA JNI 調用C/C++庫提高運行效率

    JAVA以其跨平臺的特性深受人們喜愛,而又正由於它的跨平臺的目的,使得它和本地機器的各種內部聯繫變得很少,約束了它的功能。解決JAVA對本地操作的一種方法就是JNI(Java Native Interface)。
    JAVA通過JNI調用本地方法,而本地方法是以庫文件的形式存放的(在WINDOWS平臺上是DLL文件形式,在UNIX機器上是SO文件形式)。通過調用本地的庫文件的內部方法,使JAVA可以實現和本地機器的緊密聯繫,調用系統級的各接口方法。
    好,我們現在來着手開發一個用Native方法實現的System.out.print()方法。
    首先,我們要設置一個環境變量,用來告訴虛擬機我們的C/C++庫放在哪裏,我們打開$HOME目錄下的隱藏文件.bashrc,在最下面添加一行export LD_LIBRARY_PATH=<你存放庫文件的文件夾>
    如圖:1

然後Log Out,重登錄後在終端運行命令echo $LD_LIBRARY_PATH看我們的設置是否成功
    如圖:2

然後我們建立一個JAVA工程,名爲JavaJni,再建立兩個文件,一個是我們要實驗的JNI類文件,名爲Hello.java,另外一個爲測試文件Main.java,結構下
    如圖:3

==========Hello.java
package com.sdna.jni;

public class Hello {
    static{
        System.loadLibrary("Hello");
    }
   
    static native void print(String strOut);
}

====================
==========Main.java
package com.sdna.jni;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Hello.print("Hello World!/n");
    }

}

====================
    然後我們編譯Hello.java成.class文件,然後根據Hello.class文件生成C/C++的頭文件,命令如下
    如圖:4

    然後我們建立一個C++工程,選擇Shared Library
    如圖:5

    將剛剛建立好的com_sdna_jni_Hello.h文件拖入我們剛剛建立好的C/C++工程,並建立一個com_sdna_jni_Hello.cpp文件,用來實現頭文件中聲明的方法,結構如下
    如圖:6

==========com_sdna_jni_Hello.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_sdna_jni_Hello */

#ifndef _Included_com_sdna_jni_Hello
#define _Included_com_sdna_jni_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_sdna_jni_Hello
 * Method:    print
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_sdna_jni_Hello_print
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

====================
==========com_sdna_jni_Hello.cpp
#include "com_sdna_jni_Hello.h"
#include <iostream.h>


JNIEXPORT void JNICALL Java_com_sdna_jni_Hello_print
  (JNIEnv* env, jclass jObj, jstring jStr){

    const char* pCharOut;
   
    pCharOut = env->GetStringUTFChars(jStr,0);
    cout << pCharOut;
    env->ReleaseStringUTFChars(jStr,pCharOut);
}

====================
    這時我們會發現編譯器報了很多錯誤,如下圖
    如圖:7

    不要緊,這是因爲我們沒有包含相關文件的原因,我們查看C/C++工程屬性,爲之添加兩個包含文件夾
    如圖:8

    然後我們重新編譯C/C++工程,編譯成功,我們將Debug文件夾下的.so文件考入我們最開始設置的環境變量所指向的文件夾裏,並重新命名爲libHello.so
    如圖:9

    然後我們就可以運行JAVA程序了,查看一下效果,是不是我們自己些的print函數成功了呢~呵呵

    注意,jni調用需要耗費一定時間,所以只適合於特定情況,例如:計算複雜型函數,JAVA無法實現的功能的函數等

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章