我需要通过JNI接口在Java对象和外部OCaml程序之间传输数据,但是我在访问本机代码中的对象字段时遇到了麻烦。
在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程序员指南中的字段和方法章节来检查可能的错误,但在我看来,我在书中做了所有事情。更有经验的人是否会如此友善并指出问题可能出在哪里?
答案 0 :(得分:2)
(*env)->SetIntField( env, cls, fid, state.fix);
这看起来不对。您正在尝试设置对象实例字段,但是您要传递cls
而不是jstate
作为要访问的对象。您应该使用以下代码:
(*env)->SetIntField( env, jstate, fid, state.fix);
同时对其他Set<type>Field
来电进行相应的更改。