【问题标题】:JRE SIGSEGV when running JNI native code运行 JNI 本机代码时的 JRE SIGSEGV
【发布时间】:2011-09-19 01:41:21
【问题描述】:

我需要通过 JNI 接口在我的 Java 对象和外部 OCaml 程序之间传输数据,但我无法访问本机代码中的对象字段。

在 Java 方面,我有一个包含多个字段的类:

public class GPSState {

        int fix;
        double course;
        double hmsl;
        ...
}

我将GPSState 类的对象jstate 传递给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);

...

从调试打印中,我了解到类已成功定位,fixcourse 字段已正确识别和设置。但是在对course 字段执行SetDoubleField 调用后,在调用行之后立即通过调试打印确认,当我尝试访问任何其他字段时,总是会收到 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 Programmer's Guide 中的字段和方法一章来检查可能的错误,但在我看来,我所做的一切都是按照书本做的。有经验的人会这么好心并指出问题出在哪里吗?

【问题讨论】:

    标签: java java-native-interface segmentation-fault


    【解决方案1】:
    (*env)->SetIntField( env, cls, fid, state.fix);
    

    这看起来不对。您正在尝试设置一个对象实例字段,但您传递的是 cls 而不是 jstate 作为要访问的对象。您应该改用以下内容:

    (*env)->SetIntField( env, jstate, fid, state.fix);
    

    也为您的其他 Set<type>Field 调用进行相应的更改。

    【讨论】:

    • 该死的,我怎么能错过呢?谢谢,斯图尔特!
    猜你喜欢
    • 1970-01-01
    • 2013-08-02
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 2010-12-06
    • 2012-04-14
    • 1970-01-01
    相关资源
    最近更新 更多