gpt4 book ai didi

java - JNI - 从 C++ 调用 Java 方法

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:39:43 26 4
gpt4 key购买 nike

所以我一直在尝试从 C++ 调用 java 方法,但没有任何运气。这是我收到的错误:

JNI ERROR (app bug): accessed stale local reference 0x5cb00019 (index 6 in a table of size 2) VM aborting Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1)

这是我在代码中所做的(java 端):

    public class Wrapper extends Activity{
private native void initJNIBridge();
static final String TAG = "Wrapper";

protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);

initJNIBridge(); // Calls C++ function.
}

public void upgradeAdFree() {
Log.d(TAG, "Wrapper::upgradeAdFree()");
}

这是 C++ 方面:

    typedef struct JniMethodInfo_
{
JNIEnv * env;
jclass classID;
jmethodID methodID;
} JniMethodInfo;

extern "C"
{
static jobject javaObj;

// get env and cache it
static JNIEnv* getJNIEnv(void)
{

JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == jvm) {
LOGD("Failed to get JNIEnv. JniHelper::getJavaVM() is NULL");
return NULL;
}

JNIEnv *env = NULL;
// get jni environment
jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);

switch (ret) {
case JNI_OK :
// Success!
return env;

case JNI_EDETACHED :
// Thread not attached

// TODO : If calling AttachCurrentThread() on a native thread
// must call DetachCurrentThread() in future.
// see: http://developer.android.com/guide/practices/design/jni.html

if (jvm->AttachCurrentThread(&env, NULL) < 0)
{
LOGD("Failed to get the environment using AttachCurrentThread()");
return NULL;
} else {
// Success : Attached and obtained JNIEnv!
return env;
}

case JNI_EVERSION :
// Cannot recover from this error
LOGD("JNI interface version 1.4 not supported");
default :
LOGD("Failed to get the environment using GetEnv()");
return NULL;
}
}

// get class and make it a global reference, release it at endJni().
static jclass getClassID(JNIEnv *pEnv)
{
jclass ret = pEnv->FindClass(CLASS_NAME);
if (! ret)
{
LOGD("Failed to find class of %s", CLASS_NAME);
}

return ret;
}
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *methodName, const char *paramCode)
{
jmethodID methodID = 0;
JNIEnv *pEnv = 0;
bool bRet = false;

do
{
pEnv = getJNIEnv();
if (! pEnv)
{
break;
}

jclass classID = getClassID(pEnv);

methodID = pEnv->GetMethodID(classID, methodName, paramCode);
if (! methodID)
{
LOGD("Failed to find method id of %s", methodName);
break;
}

methodinfo.classID = classID;
methodinfo.env = pEnv;
methodinfo.methodID = methodID;


bRet = true;
} while (0);

return bRet;
}

JNIEXPORT void JNICALL Java_org_test_games_Wrapper_initJNIBridge(JNIEnv *, jobject jobj){
LOGD("Java_org_test_games_Wrapper_initJNIBridge()");

javaObj = jobj;

return;
}

void upgradeAdFreeJNI()
{
LOGD("upgradeAdFreeJNI");

JniMethodInfo methodInfo;
if (! getMethodInfo(methodInfo, "upgradeAdFree", "()V"))
{
LOGD("Cannot find method!");
return;
}

methodInfo.env->CallVoidMethod(javaObj, methodInfo.methodID);
}


}

这里的任何建议将不胜感激,因为我已经为此困扰了几天,而且调试它并不是世界上最简单的任务。

谢谢

最佳答案

问题是您指向作业对象的静态指针不再有效。您需要保护它免受任何垃圾收集器运行的影响。这可以通过使用全局引用而不是本地引用来完成。而不是仅仅分配指针创建一个 globalRef。

JNIEXPORT void JNICALL Java_org_test_games_Wrapper_initJNIBridge(JNIEnv *, jobject jobj)
{
LOGD("Java_org_test_games_Wrapper_initJNIBridge()");

javaObj = env->NewGlobalRef(env, jobj);

return;
}

但请注意,您还必须释放 globafRef。

关于java - JNI - 从 C++ 调用 Java 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14836671/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com