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无法实现的功能的函数等
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无法实现的功能的函数等
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.