将对象创建移动到另一个方法后出现JNI Bus错误 [英] JNI Bus error after moving object creation to another method

查看:167
本文介绍了将对象创建移动到另一个方法后出现JNI Bus错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个JNI的问题,这一整天都把我带走了,如果我不打电话求助,可能会让我感到疯狂。

I have a problem with JNI that has taken me all day and will probably drive me insane if I don't call for help.

两个短语:我从JNI方法调用一个NewObject并且它工作正常,但是当我将此代码移动到另一个方法时,它会崩溃。

In two phrases: I call a NewObject from a JNI method and it works fine, but when I moved this code to another method, it crashes.

更多细节:

我有这个简单的类,我想从JNI C / C ++代码创建它的实例:

I have this simple class, and I want to create instances of it from the JNI C/C++ code:

package example;

public class ModelDetails {
    public ModelDetails() { ... }
}

具有本机方法的类如下:

The class with the native method is as follows:

package example;
public class JNIWrapper {
     public native ModelDetails getModelDetails() throws SomeException;
}

以下代码效果非常好:

jclass    modelDetailsClass           = NULL;
jmethodID modelDetailsConstMid        = NULL;

JNIEXPORT jobject JNICALL Java_example_JNIWrapper_getModelDetails
 (JNIEnv *env, jobject jobj) {

    cout << "getModelDetails c++" << endl;

    // ModelDetails class
    if (!modelDetailsClass) { // reuse class
        modelDetailsClass = env->FindClass("example/ModelDetails");
    }
    if (!modelDetailsClass) { // check if findclass was successful
        throwJavaException(env, "Could not get class ModelDetails");
        return NULL;
    }
    cout << "model detail class: " << modelDetailsClass << endl;

    // constructor
    if (!modelDetailsConstMid) { // reuse method id
        modelDetailsConstMid = env->GetMethodID(modelDetailsClass, "<init>", "()V");
    }
    if (!modelDetailsConstMid) { // check if getmethodid was successful
        throwJavaException(env, "Could not get ModelDetails constructor method id");
        return NULL;
    }

    // create object
    jobject mdetails = env->NewObject(modelDetailsClass, modelDetailsConstMid);
    if (!mdetails) {
        throwJavaException(env, "Could not create ModelDetails instance");
        return NULL;
    }
    return mdetails;
}

但是,因为我必须在这个函数中做很多事情 Java_example_JNIWrapper_getModelDetails ,我决定将此对象的创建移动到另一个函数:

However, since I have to do a lot of things in this function Java_example_JNIWrapper_getModelDetails, I decided to move the creation of this object to another function:

jobject fillModelDetails(JNIEnv *env, jobject jobj) {
    cout << "fillModelDetails" << endl;

    // ModelDetails class
    if (!modelDetailsClass) { // reuse class
        modelDetailsClass = env->FindClass("example/ModelDetails");
    }
    if (!modelDetailsClass) { // check if findclass was successful
        throwJavaException(env, "Could not get class ModelDetails");
        return NULL;
    }
    cout << "model detail class: " << modelDetailsClass << endl;

    // constructor
    if (!modelDetailsConstMid) { // reuse method id
        modelDetailsConstMid = env->GetMethodID(modelDetailsClass, "<init>", "()V");
    }
    if (!modelDetailsConstMid) { // check if getmethodid was successful
        throwJavaException(env, "Could not get ModelDetails constructor method id");
        return NULL;
    } 

    // create object
    jobject mdetails = env->NewObject(modelDetailsClass, modelDetailsConstMid);
    if (!mdetails) {
        throwJavaException(env, "Could not create ModelDetails instance");
        return NULL;
    }

    return mdetails;
}

这样,在 Java_example_JNIWrapper_getModelDetails 我只是调用 fillModelDetails(env,jobj);

问题是现在我得到一个总线错误在 NewObject 行。

The problem is that now I get a bus error at the NewObject line.

Invalid memory access of location 0x9 eip=0x475fe1

问题
有谁知道为什么我不应该从另一个方法调用构造函数?这看起来很奇怪。

Question: Does anyone know why I should not be calling a constructor from another method? It seems really weird.

感谢任何提示,想法,评论...

Thanks for any tip, idea, comments...

编辑:

我刚刚添加了 -Xcheck:jni 并收到此错误:

I've just added -Xcheck:jni and got this error:

FATAL ERROR in native method: Bad global or local ref passed to JNI
at example.JNIWrapper.getModelDetails(Native Method)

所以这让我觉得问题可能是通过使用全局变量中的构造函数和类id引起的。我将这些声明移动到JNI方法中的局部变量并且它可以工作。

So this gave me the idea that the problem might be caused by using the constructor and class id from a global variable. I moved these declarations to a local variable in the JNI method and it works.

这真让我感到惊讶,因为我从一段时间以来一直在使用这些全局变量而且从不有任何问题......可能导致这个问题的原因是什么?

This really astonishes me because I've been using these global variables from some time now and never had any problems... what could be causing this problem?

推荐答案

我会回答这个问题,因为我发现了问题,关于重新使用 jclass jmethodID 的问题仍然存在。在这个方向上改变这个问题似乎没有组织,所以我将打开另一个线程。

I will answer this since I found the problem, however another question remains regarding re-using the jclass and jmethodID. Changing this question in that direction does not seem organized, so I will open another thread.

解决方案是使用局部变量

The solution was to use local variables for

jclass    modelDetailsClass           = NULL;
jmethodID modelDetailsConstMid        = NULL;

而不是我之前使用的全局变量。

instead of the global variables that I was using before.

这篇关于将对象创建移动到另一个方法后出现JNI Bus错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆