JNI错误总结(转)
源:JNI错误总结
最近公司里要用JNI技术,用java去调用已经写好的本地DLL库。之前自己也没接触过相关技术,其中花了大部分时间在调试改错上面,网上对于错误的解决方案也不多,现在项目接近完工,自己也该把其中碰到的一些问题进行一下汇总。
1.相关命令:
将包含native函数的java源代码生成JNI的.h头文件: javah -jni com.xxx.test
注意:test是编译后的.class文件,要写完整路径,该命令在com的上层目录下进行。更完整的命令为: javah -classpath . -jni com.xxx.test 注意中间的点号
编写实现上面.h文件的.cpp代码后,生成dll目标文件:g++ -Wl,--kill-at -shared -o test1.dll test2.cpp
注意:test1.dll为生成的目标DLL,test2为cpp源文件。红色部分不可少,表示生成不带@的函数.
2.如何将java里的string类型转换为C里的char*类型:
char* jstringTostring(JNIEnv* env, jstring jstr) //change type string into char*
{
char* rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0)
{
rtn = (char*)malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return rtn;
}
3.如何将C里的char*类型转换为java里的string类型:
jstring stoJstring(JNIEnv* env, const char* pat)//change type char* into string
{
jclass strClass = env->FindClass("Ljava/lang/String;");
jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
jbyteArray bytes = env->NewByteArray(strlen(pat));
env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);
jstring encoding = env->NewStringUTF("utf-8");
return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
}
4.JNI里如何返回arraylist类型:
jclass cls_ArrayList = env->FindClass("java/util/ArrayList");
jmethodID construct = env->GetMethodID(cls_ArrayList,"<init>","()V");//注意第二个参数为<init>,网上有些资料写着为空或者<init></init>是错的。
jobject obj_ArrayList = env->NewObject(cls_ArrayList,construct,"");
jmethodID arrayList_add = env->GetMethodID(cls_ArrayList,"add","(Ljava/lang/Object;)Z"); //获得arraylist的add()方法
//User Object
jclass cls_user = env->FindClass("User"); //注意User所在路径要写完整,该加包名的地方要加上
//none argument construct function
jmethodID construct_user = env->GetMethodID(cls_user,"<init>","()V");
//new a object
jobject obj_user = env->NewObject(cls_user,construct_user,"");
//get method id
/*
jmethodID user_setId = env->GetMethodID(cls_user,"setId","(J)V");
jmethodID user_setUserName = env->GetMethodID(cls_user,"setUserName","(Ljava/lang/String;)V");
jmethodID user_setMan = env->GetMethodID(cls_user,"setMan","(Z)V");
jmethodID user_setAge = env->GetMethodID(cls_user,"setAge","(I)V");
*/
int i;
for(i=0;i<10;i++){
//new a object
jobject obj_user = env->NewObject(cls_user,construct_user,"");
//get field id
jfieldID user_id = env->GetFieldID(cls_user,"id","J");
jfieldID user_name = env->GetFieldID(cls_user,"userName","Ljava/lang/String;");
jfieldID user_isMan = env->GetFieldID(cls_user,"isMan","Z");
jfieldID user_age = env->GetFieldID(cls_user,"age","I");
env->SetLongField(obj_user,user_id,i);
env->SetObjectField(obj_user,user_name,env->NewStringUTF("CC"));
env->SetBooleanField(obj_user,user_isMan,1);
env->SetIntField(obj_user,user_age,21);
env->CallObjectMethod(obj_ArrayList,arrayList_add,obj_user);
}
return obj_ArrayList;
}
5.对于碰到以下错误:
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x7c92100b, pid=596, tid=2080
#
# JRE version: 6.0_21-b07
# Java VM: Java HotSpot(TM) Client VM (17.0-b17 mixed mode, sharing windows-x86 )
# Problematic frame:
# C [ntdll.dll+0x100b]
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
一般都是由于你所写的JNI转换后的CPP实现代码有问题。可以关注下红色部分,若pc=0x00000000,则表示你要实现的native函数里传入了空指针void*或null。
而如果你传入的参数还有结构体变量,那么这里的空值还要考虑结构体里的部分成员是否也为空,JNI里的函数是不允许传入空值的,这点网上的资料里都没有提,我也在这里卡了很久。但是你必须要传入空值,而且还要调用更下一层的DLL里的函数时,那就会报错,这时该怎么办呢?此时你可以在它们中间再加一过渡层(CPP文件)实现间接调用。
6.最后注意下JNI里的资源释放问题,若使用资源过多没有及时释放,也会有可能会报上面的错误。
如:env->ReleaseStringUTFChars(xxx, xxx);
至于其他问题网上都有就不写了。
JNI错误总结(转)的更多相关文章
- JNI错误记录--JNI程序调用本地库时JVM崩溃
什么是JNI内存泄露,基本的避免方法 : http://www.ibm.com/developerworks/cn/java/j-lo-jnileak/ 最近的课题中需要用到Spark,同组同学负责的 ...
- AndroidStudio NDK配置使用以及错误集合
Error:Execution failed for task ':app:transformNative_libsWithStripDebugSymbolForDebug'. > java.l ...
- JNI 记
Java Native Interface(JNI)从零开始详细教程 ================================================================ ...
- JNI 入门
1.http://cherishlc.iteye.com/blog/1756762 Android 学习笔记--利用JNI技术在Android中调用.调试C++代码 2.http://my.eoe.c ...
- Java -verbose[:class|gc|jni] 转 ----JAVA源码分析
http://blog.csdn.net/tenderhearted/article/details/39642275 http://www.cnblogs.com/iceAeterNa/p/4876 ...
- JNI 引用问题梳理(转)
局部引用: JNI 函数内部创建的 jobject 对象及其子类( jclass . jstring . jarray 等) 对象都是局部引用,它们在 JNI 函数返回后无效: 一般情况下,我们应该依 ...
- Android 应用程序升级到 5.0 需要注意的问题
Android 5.0,代号 Lollipop,源码终于在2014年12月3日放出,国内一大批厂商跟进.最大的改变是默认使用 ART(Android Runtime) ,替换了之前的 Dalvik 虚 ...
- Java 命令行运行参数大全
Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOME"bin"java –option 来启动,-option为虚拟 ...
- Java命令参数说明大全
Java 在运行已编译完成的类时,是通过 java 虚拟机来装载和执行的,java 虚拟机通过操作系统命令 JAVA_HOME\bin\java –option 来启动,-option 为虚拟机参数, ...
随机推荐
- java 基础之概念
1:栈(Stack) 先进后出(邮政模拟例) 2:队列(Queue) 先进先出(排队购票)
- NPOI 2.0 教程(二):编辑既存的EXCEL文件
NPOI 2.0 教程(二):编辑既存的EXCEL文件 分类: C#技术 2014-03-11 15:40 993人阅读 评论(3) 收藏 举报 c#excelNPOI 转载请注明出处 http:// ...
- If only it could be all the same like we first me
为什么 你当时对我好 Why? You nice to me at that time. 又为什么 现在变得冷淡了 Why? Now you give a cold shoulder to me. 我 ...
- 转:Eclipse Debug 界面应用详解——Eclipse Debug不为人知的秘密
今天浏览csdn,发现一文详细的描述了Eclipse Debug中的各个知识点,非常详尽!特此记录. Eclipse Debug不为人知的秘密 http://blog.csdn.net/mgoann/ ...
- 用MyEclipse自动生成hibernate映射文件和实体类
创建数据库,创建相应的表 点击图标,选择MyEclipse Datebase Explorer 右击空白区域,选择new菜单,根据提示创建数据库连接,创建好后会显示你所创建的连接名,如图mysqldb ...
- Opencv 图像叠加 添加水印
Opencv 图像叠加 添加水印 C++: void Mat::copyTo(OutputArray m) const C++: void Mat::copyTo(OutputArray m, Inp ...
- 测试redis+keepalived实现简单的主备切换【转载】
转自: 测试redis+keepalived实现简单的主备切换 - Try My Best 尽力而为 - ITeye技术网站http://raising.iteye.com/blog/2311757 ...
- Linux SCP命令复制传输文件的用法
SCP命令是用户通过网络将一台Linux服务器的文件复制到另一台Linux服务器,方法如下: 一:从本地复制到远程 复制文件: 命令格式: scp local_file remote_username ...
- jquery has deprecated synchronous XMLHTTPRequest
Like many others, my website is using jquery. When I open the developer tools, I see a warning that ...
- 【百度地图开发之二】基于Fragment的地图框架的使用
写在前面的话: [百度地图开发之二]基于Fragment的地图框架的使用(博客地址:http://blog.csdn.net/developer_jiangqq),转载请注明. Author:hmji ...