您的位置:首页 > 编程语言 > C语言/C++

ubuntu下,C/C++通过JNI调用 JAVA类

2010-04-13 19:16 447 查看
之前写过一个实现了某种功能的java程序,但由于近日“工作”需要,又需要在c/c++中重新使用该功能。为了节省时间,我采取了在c/c++中调用java程序的方法,但之前没有接触过类似的东西,到网上一查,果然有类似的东西,心中暗喜ing...。查到的资料中有几个不错的网页:
http://blog.sina.com.cn/s/blog_48eef8410100fjxr.html http://www.diybl.com/course/6_system/linux/Linuxjs/20100331/201638.html
http://hi.baidu.com/pjdashu/blog/item/5e54df9961040d006e068c1b.html

第一个网址,主要介绍了安装java环境和编译过程;

第二个网址,主要介绍了jni的使用方法。第三个网址,最后的代码比较明确的说明了如何使用里面的字符串,可以直接看最后一段的代码。我按照第一个网址的方法进行实验,发现了好多的问题。先把主要应该注意的地方记录如下:

(我使用的环境是:Ubuntu8.04)

安装配置Java环境以及编译


安装java环境时,我参照了 http://wiki.ubuntu.org.cn/Java安装配置
的安装配置方法,安装的是java6。下面的配置路径可能根据系统的不同,略有不同。在ubuntu下默认是安装到了/usr/lib/jvm下。

然而,此处的说法:“
要使配置生效必须重启机器或者在命令行输入
”并不完全正确,最起码对于LD_LIBRARY_PATH来说不正确,因为有资料显示:

貌似 Ubuntu 不能在 profile, environment,.bashrc中设置 LD_LIBRARY_PATH,
可以这样解决库装载问题:

编辑 /etc/ld.so.conf 文件,将指定的路径加上,或者在 /etc/ld.so.conf.d/
目录中添加一个新的配置文件,内容看一下该目录下其它文件就明白了。。。当然你得有权限这么做。(http://forum.ubuntu.org.cn/viewtopic.php?f=56&t=94830


我的做法
要么每次使用之前,要么先运行“. /etc/environment”,要么“export LD_LIBRARY_PATH=

$JRE_HOME/lib/i386/client”

配置过程中我还参照了第一个网址中的内容:

JAVA_HOME=/usr/local/java/jdk1.5.0_06
PATH=$PATH:/usr/local/java/jre1.5.0_05/bin
export JAVA_HOME PATH
export
JRE_HOME=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
export
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JRE_HOME/lib/i386:$JRE_HOME/lib/i386/client
在设置环境变量LD_LIBRARY_PATH时,按照此URL中内容无法实现。在编译通过后,执行时候总是报错:
(briver)-(jobs:0)-(~/JCplus)
(! 552)-> g++ -o testjava testjava.cpp -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -L"$JRE_HOME/lib/i386/client " -ljvm
testjava.cpp: In function ‘int main()’:
testjava.cpp:61: warning: deprecated conversion from string constant to ‘char*’
testjava.cpp:62: warning: deprecated conversion from string constant to ‘char*’
(briver)-(jobs:0)-(~/JCplus)
(! 553)-> ./testjava
./testjava: error while loading shared libraries: libjvm.so: cannot open shared object file: No such file or directory
最后,我将 LD_LIBRARY_PATH 设置为了export LD_LIBRARY_PATH=$JRE_HOME/lib/i386/client。并改变了编译时候取libjvm.so路径的方式,编译并执行通过:
(briver)-(jobs:0)-(~/JCplus)
(! 541)-> g++ -o testjava testjava.cpp -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux -L${LD_LIBRARY_PATH} -ljvm
testjava.cpp: In function ‘int main()’:
testjava.cpp:61: warning: deprecated conversion from string constant to ‘char*’
testjava.cpp:62: warning: deprecated conversion from string constant to ‘char*’
(briver)-(jobs:0)-(~/JCplus)
(! 542)->./testjava
1
2
create java jvm success
find java class success
init ok
10
Boolean ok
Java VM destory.


出现在jni使用过程中的java.lang.OutOfMemoryError: Java heap space
错误

jni运行一段时间就会因java.lang.OutOfMemoryError: Java heap space而终止。如果是在纯java环境中,我们可以使用脚本:JAVA -Xms80m -Xmx256m -jar yourApp.jar,但是程序现在的运行情景是:linux下通过c/c++使用jni调用java,幸好的是jdk1.2开始支持了这种设置:

你可以在虚拟机初始化的时候,指定响应的选项,例如:

options[0].optionString = "-Xms4M";
options[1].optionString = "-Xmx64M";
options[2].optionString = "-Djava.class.path=.";
vm_args.version = JNI_VERSION_1_4;
vm_args.options = options;
vm_args.nOptions =3;//与options的数目相一致


这样就对jvm指定最大内存设为64m,最小为4m。(Xms Xmx:这篇文章也许对你有帮助http://1zebra.javaeye.com/blog/561027
)。如果你这样做了,发现问题仍然没有得到解决,那么你应该从自己的代码入手,解决这个问题了,下面一段代码对你会有帮助的:

JNIEnv *env;

jclass clsHASHMAP;

jmethodID ArrayList_add, ArrayList_get, ArrayList_size, HashMap_put, HashMap_init;

jstring key, value;

jobject objHashMap;

/* get class. */

clsHASHMAP = (*env)->FindClass(env,"Ljava/util/HashMap;");

/* get init method for HashMap */

HashMap_init = (*env)->GetMethodID(env,clsHASHMAP, "<init>", "()V");

/* Call HashMap.init() to get a hashmap object */

objHashMap = (*env)->NewObject(env, clsHASHMAP, HashMap_init);

HashMap_put = (*env)->GetMethodID(env, *clsHASHMAP, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");

key = (*env)->NewStringUTF(env, "xxx");

Value = (*env)->NewStringUTF(env, "xxx");

/* put key/value to hashmap. */

(*env)->CallObjectMethod(env, objHashMap, HashMap_put, key, value);

/* 内存回收 */

(*env)->DeleteLocalRef(env, key);

(*env)->DeleteLocalRef(env, value);

(*env)->DeleteLocalRef(env, objHashMap);

也就是说要注意资源的释放(http://hyy115.blog.sohu.com/105289076.html
)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: