运行JNI本机代码时JRE SIGSEGV
问题描述:
我需要通过JNI接口在我的Java对象和外部OCaml程序之间传输数据,但我有麻烦来访问本机代码中的对象字段。运行JNI本机代码时JRE SIGSEGV
在Java方面,我有几个字段类:
public class GPSState {
int fix;
double course;
double hmsl;
...
}
我传递一个对象jstate
的GPSState
级到C部分,在这里我想设置其字段通过外部程序提供相应的值被保存在本地结构state
:
jclass cls;
jfieldID fid;
cls = (*env)->GetObjectClass(env, jstate);
fid = (*env)->GetFieldID(env, cls, "fix", "I");
(*env)->SetIntField(env, cls, fid, state.fix);
fid = (*env)->GetFieldID(env, cls, "course", "D");
(*env)->SetDoubleField(env, cls, fid, state.course);
fid = (*env)->GetFieldID(env, cls, "hmsl", "D");
(*env)->SetDoubleField(env, cls, fid, state.hmsl);
...
从调试打印我学到了类表被成功定位和fix
和course
字段被正确识别和设置。但是,SetDoubleField
呼吁对course
领域,这是一个调试打印确认马上打电话线以下执行后,我总是得到SIGSEGV致命错误,当我尝试访问任何其他领域:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x01109720, pid=11665, tid=3079347056
#
后来我有发现,当我将操纵course
字段的代码移动到设置字段的C函数的最后时,错误消失并且所有字段都按预期设置,没有任何问题。
我试着用另一个JRE实现运行另一台机器上的代码,但结果是一样的,除了在设置第一个fix
字段后发生的错误(将代码的相应位移动到功能“再次解决”了这个问题)。
现在,我知道我不知何故搞乱了记忆,但我无法弄清楚在哪里以及如何。我遵循JNI程序员指南中的字段和方法章节来检查可能的错误,但在我看来,我完成了本书的所有工作。有人更有经验会如此善良,并指出问题出在哪里?
答
(*env)->SetIntField(env, cls, fid, state.fix);
这看起来不对。您正试图设置一个对象实例字段,但是您要传递cls
而不是jstate
作为要访问的对象。您应该改用以下内容:
(*env)->SetIntField(env, jstate, fid, state.fix);
让您的其他Set<type>Field
调用相应的改变。
该死的,我怎么会想念那个?谢谢,斯图尔特! – petok