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无法实现的功能的函数等

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