【问题标题】:Error while calling non static java method from c++从 C++ 调用非静态 Java 方法时出错
【发布时间】:2015-04-08 13:50:23
【问题描述】:

我有类似的 jni cpp 类

JNIEXPORT void JNICALL Java_com_my_package_GameBridge_startGame(JNIEnv *env, 
                                                                    jobject obj)) 
{
    GameBridge_Android gameBridge;
    JavaVM* jvm;
    int status = env->GetJavaVM(&jvm);
    // global reference
    jobject globalRef = env->NewGlobalRef(obj)
    gameBridge.setCallback(globalRef);
    gameBridge.startGame();
}

我正在尝试将 jobject 的引用存储为全局引用,并且只要我需要,我就可以在该对象上调用 java 方法。

我决定创建纯 c++ 类 - GameBridge_Android
C++ 标头与此类似

GameBridge_Android.h:

class GameBridge_Android : public GameBridge
{
public:
    GameBridge_Android();
    virtual void startGame();
    virtual void restartGame();
    virtual void pauseGame();
    virtual void resumeGame();
    virtual void setCallback(jobject obj);

protected:
    jobject mCallback;
};

及其实现

GameBridge_Android.cpp:

void GameBridge_Android::restartGame(){//....}
void GameBridge_Android::resumeGame(){//....}
void GameBridge_Android::setCallback(jobject callback)
{
     mCallback = callback;
}

void GameBridge_Android::pauseGame()
{
    JavaVM* vm = JniHelper::getJavaVM();
    JNIEnv* env;
    jint rs = vm->AttachCurrentThread(&env, NULL); 

    jclass cls = env->FindClass("com/my/package/GameBridge");
    jmethodID onPause = env->GetMethodID(cls, "onPause", "()V");
    env->CallVoidMethod(mCallback, onPause);
}

还有简单的java GameBridge 类

public class GameBridge {
    public native void startGame();

    public void onPause() {
        Log.d("JAVA_GameBridge", "onPause called ");
    }
}

我遇到了一个错误

 art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: native          code passing in reference to invalid global reference: 0x736c6576

 04-08 16:33:57.889  25537-29355/com.my.package A/art﹕  art/runtime/check_jni.cc:65]  in call to CallVoidMethodV

我尝试将 jobject 引用更改为全局引用,但没有成功(可能我在这里做错了) 但是,当我调用静态 java 方法时,一切正常。

附:我不是 C++ 开发人员,因此非常感谢您对此部分的任何建议和更正。

【问题讨论】:

  • 为什么gameBridge是Java_com_my_package_GameBridge_startGame()中的一个局部变量?当函数完成时,它将被销毁
  • @samgak 你是对的,将游戏桥作为静态变量可能会更好。
  • 那么,你找到解决这个问题的方法了吗?
  • @RenatoUtsch 不要在本机内存中保留对非静态 java 对象的引用。 Android 的 VM(Dalvik 或 ART)可以对对象做任何他们想做的事情(移动对象、垃圾等),因此无法保证引用会指向您期望的对象。

标签: android c++ cocos2d-iphone java-native-interface


【解决方案1】:

首先,检查 FindClass() 和 GetMethodID() 等调用的每个结果是否为 NULL。如果你得到一个 NULL,使用类似 "cerr..." 或 "fprintf(stderr, ...)" 来立即发出一个非常描述性的错误信息。

其次,自从我尝试做一些非常接近你正在做的事情以来已经有几年了,所以我不确定,但我认为你不能引用传递给本机非静态方法的 jobject在传递给它的调用的上下文之外调用。您可能需要使用来自 NewGlobalRef() 的全局引用。

JNI 非常无情。

这是将线程附加到 JVM 的另一种方法:How to obtain JNI interface pointer (JNIEnv *) for asynchronous calls

我似乎记得那更像是我成功的那个。

【讨论】:

  • 检查完成,此时一切正常。我试图将指向 jobject 的指针设为全局,但它没有起到作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
  • 1970-01-01
相关资源
最近更新 更多