JNI_OnLoad() 中的 GetEnv 出错,删除这些行时应用程序崩溃,错误消失
Getting error while GetEnv in JNI_OnLoad() and app crashing when removed these lines, error goes away
应用程序在 JNI_OnLoad() 中崩溃。我检查了它的状态为零。尽管如此,该应用程序仍在崩溃。我想创建环境变量来缓存方法 ID,以便将它们用于 java 函数的回调。我尝试在上下文结构中缓存 jvm 并在 callback() 方法中执行相同操作,但 App 崩溃了。我是这个概念的新手。谁能解释一下我在这里缺少什么。
请查找附件代码:
#include <jni.h>
#include <string>
#include "Numbers.h"
#include <android/log.h>
#define LOG_TAG "logs"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
typedef struct number_ctx{
JavaVM *javaVM;
jclass mathsClass;
jobject mathsObj;
jclass mainActivityClass;
jobject mainActivityObj;
pthread_mutex_t lock;
} NumbersCtx;
NumbersCtx g_ctx;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
memset(&g_ctx, 0, sizeof(g_ctx));
g_ctx.javaVM = vm;
int status = vm ->GetEnv((void **)env, JNI_VERSION_1_6);
LOGD("Status is %d ", status);
if (vm ->GetEnv((void **)env, JNI_VERSION_1_6) != JNI_OK) {
LOGD("Some error");
return JNI_ERR; // JNI version not supported.
}
if(env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
/*
jclass clz = env->FindClass(
"com/example/maths/Maths1");
g_ctx.mathsClass = static_cast<jclass>(env->NewGlobalRef(clz));
jmethodID jniHelperCtor = env->GetMethodID(g_ctx.mathsClass,
"printMessage", "()V");
jobject handler = env->NewObject(g_ctx.mathsClass,
jniHelperCtor);
g_ctx.mathsObj = env->NewGlobalRef(handler);
g_ctx.mainActivityObj = NULL;*/
return JNI_VERSION_1_6;
}
void callback() {
}
您在调用 GetEnv
时忘记使用 Address-Of 运算符 (&
)。 GetEnv
需要一个指向指针的指针,但您只是将一个指针传递给它,然后将其转换为指向指针的指针,这不是一回事。
所以不用
vm ->GetEnv((void **)env, JNI_VERSION_1_6)
你应该使用
vm ->GetEnv((void **)&env, JNI_VERSION_1_6)
在这种情况下省略 Address-Of 运算符的最终结果是 GetEnv
将存储 JNIEnv*
who-knows-where,而您的 env
变量最有可能不会包含有效的 JNIEnv*
.
应用程序在 JNI_OnLoad() 中崩溃。我检查了它的状态为零。尽管如此,该应用程序仍在崩溃。我想创建环境变量来缓存方法 ID,以便将它们用于 java 函数的回调。我尝试在上下文结构中缓存 jvm 并在 callback() 方法中执行相同操作,但 App 崩溃了。我是这个概念的新手。谁能解释一下我在这里缺少什么。
请查找附件代码:
#include <jni.h>
#include <string>
#include "Numbers.h"
#include <android/log.h>
#define LOG_TAG "logs"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
typedef struct number_ctx{
JavaVM *javaVM;
jclass mathsClass;
jobject mathsObj;
jclass mainActivityClass;
jobject mainActivityObj;
pthread_mutex_t lock;
} NumbersCtx;
NumbersCtx g_ctx;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
memset(&g_ctx, 0, sizeof(g_ctx));
g_ctx.javaVM = vm;
int status = vm ->GetEnv((void **)env, JNI_VERSION_1_6);
LOGD("Status is %d ", status);
if (vm ->GetEnv((void **)env, JNI_VERSION_1_6) != JNI_OK) {
LOGD("Some error");
return JNI_ERR; // JNI version not supported.
}
if(env->ExceptionCheck()) {
env->ExceptionDescribe();
env->ExceptionClear();
}
/*
jclass clz = env->FindClass(
"com/example/maths/Maths1");
g_ctx.mathsClass = static_cast<jclass>(env->NewGlobalRef(clz));
jmethodID jniHelperCtor = env->GetMethodID(g_ctx.mathsClass,
"printMessage", "()V");
jobject handler = env->NewObject(g_ctx.mathsClass,
jniHelperCtor);
g_ctx.mathsObj = env->NewGlobalRef(handler);
g_ctx.mainActivityObj = NULL;*/
return JNI_VERSION_1_6;
}
void callback() {
}
您在调用 GetEnv
时忘记使用 Address-Of 运算符 (&
)。 GetEnv
需要一个指向指针的指针,但您只是将一个指针传递给它,然后将其转换为指向指针的指针,这不是一回事。
所以不用
vm ->GetEnv((void **)env, JNI_VERSION_1_6)
你应该使用
vm ->GetEnv((void **)&env, JNI_VERSION_1_6)
在这种情况下省略 Address-Of 运算符的最终结果是 GetEnv
将存储 JNIEnv*
who-knows-where,而您的 env
变量最有可能不会包含有效的 JNIEnv*
.