Qt安卓开发中Java Activity调用C++方法触发JNI崩溃如何解决?
问题原因
- 核心错误出现在
registerJni方法的QAndroidJniObject javaClass("org/test/testproject/TestActivity")代码行:- 该写法会尝试调用TestActivity的无参构造函数直接实例化Activity对象
- Activity属于安卓系统管控的生命周期组件,不允许开发者手动实例化,必须由系统按照进程调度流程创建
- 手动实例化时,Activity构造函数内部会初始化Handler组件,但当前执行注册逻辑的线程没有调用
Looper.prepare()初始化消息循环,因此直接抛出运行时异常
- 注册阶段抛出的异常没有被及时捕获处理,一直处于JNI pending状态,后续Java端调用native方法时,JNI运行时检测到待处理异常直接触发崩溃
- 额外潜在问题:
onResultRead方法中调用GetStringUTFChars获取的字符串资源没有调用ReleaseStringUTFChars释放,会造成JNI层内存泄漏。
解决方案
核心修改逻辑为:注册JNI方法时不需要实例化Activity对象,直接通过类路径获取jclass结构体即可。
修正后C++代码
#include <QDebug> #include <QtAndroid> // Qt5环境引入,Qt6请引入QNativeInterface::QAndroidApplication相关头文件 static void onResultRead(JNIEnv *env, jobject /*thiz*/, jstring value) { const char *resultStr = env->GetStringUTFChars(value, nullptr); qDebug() << "收到Java侧传递结果:" << resultStr; env->ReleaseStringUTFChars(value, resultStr); // 释放JNI字符串资源,避免内存泄漏 } void MyClass::registerJni() { QAndroidJniEnvironment env; // 直接通过类路径获取jclass,不需要实例化Activity jclass activityClass = env->FindClass("org/test/testproject/TestActivity"); if (activityClass == nullptr) { qWarning() << "JNI注册失败:未找到TestActivity类,请检查类路径是否正确"; return; } JNINativeMethod methods[] = { {"resultRead", "(Ljava/lang/String;)V", reinterpret_cast<void *>(onResultRead)} }; int registerRet = env->RegisterNatives(activityClass, methods, sizeof(methods) / sizeof(methods[0])); if (registerRet < 0) { qWarning() << "JNI方法注册失败,错误码:" << registerRet; } env->DeleteLocalRef(activityClass); }
其他注意事项
- 注册时机建议选在Qt应用初始化完成、Activity已经被系统成功创建之后执行,可放在
main函数中QApplication实例初始化后、exec()方法调用前执行。 - 若使用Qt6版本,
QAndroidJniEnvironment相关API已迁移到QNativeInterface::QAndroidApplication命名空间下,需对应调整头文件引入和API调用方式。
内容的提问来源于stack exchange,提问作者Fausto01
相关产品推荐
相关产品推荐

