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”
配置过程中我还参照了第一个网址中的内容:
出现在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开始支持了这种设置:
你可以在虚拟机初始化的时候,指定响应的选项,例如:
这样就对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
)。
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
)。
相关文章推荐
- java与C/C++之间通过jni相互调用
- Cocos2d-x通过Jni实现C++与Java相互调用
- Java通过JNI调用C++程序
- android jni c/c++线程通过CallVoidMethod调用java函数出现奔溃问题
- Ubuntu下,Java中利用JNI调用codeblocks c++生成的动态库的使用步骤
- Java通过JNI调用C++程序
- 在Android中,通过JNI实现C++与Java相互调用
- Java 通过 Jni 调用 C++代码
- AndroidJNI 通过C++调用JAVA
- scala和java通过JNI调用C++程序例子
- 安卓应用开发通过java调用c++ jni的图文使用方法
- Java通过JNI调用C++程序
- java通过jni native method 调用非java语言的代码,例:c++
- Java通过JNI调用C++程序
- linux系统下通过jni用c++调用java
- C++ 通过JNI调用Java
- AndroidJNI 通过C++调用JAVA
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)
- 通过JNI实现Java和C++的相互调用(转)