JNI调用C++方法时出现NoSuchMethodError问题求助
解决JNI编译正常但运行时方法不可见的问题
你的问题核心是JNI方法签名不匹配,导致JVM无法找到对应的本地方法,同时代码里还有几处逻辑问题,逐一修正如下:
1. 修正JNI方法的返回值类型
Java端的native方法返回boolean,但你的JNI代码里声明的是JNIEXPORT void,这会导致方法签名完全不匹配,JVM找不到对应方法。
修改JNI函数的返回值为jboolean,并返回对应结果:
//fxcl.hsm.log.TraceLog.getLogs extern "C" JNIEXPORT jboolean JNICALL Java_fxcl_hsm_log_TraceLog_getLogs (JNIEnv *ptEnv, jobject ptObj, jobject tVecLogs, jint tUiNumLines) { TraceLog& tLog=getDevice(*ptEnv, ptObj); std::vector<ByteArray> vecLogs; unsigned int uiNumLines=static_cast<unsigned int>(tUiNumLines); bool bRet = tLog.getLogs(vecLogs, uiNumLines); //convert to a vector of Java objects std::vector<jobject> vecJavaLogs; vecJavaLogs.reserve(vecLogs.size()); for (auto iter = vecLogs.begin(); iter < vecLogs.end(); ++iter) vecJavaLogs.push_back(JniConvert::byteArray_uncast(*ptEnv, *iter)); // 获取ArrayList的addAll方法,将转换后的元素添加到传入的列表中 jclass arrayListCls = ptEnv->GetObjectClass(tVecLogs); jmethodID addAllMethod = ptEnv->GetMethodID(arrayListCls, "addAll", "(Ljava/util/Collection;)Z"); jobject javaList = JniObjectSet::toJava(*ptEnv, vecJavaLogs, "java/util/ArrayList"); ptEnv->CallBooleanMethod(tVecLogs, addAllMethod, javaList); // 释放局部引用 ptEnv->DeleteLocalRef(arrayListCls); ptEnv->DeleteLocalRef(javaList); return bRet ? JNI_TRUE : JNI_FALSE; }
2. 修正ArrayList参数的处理逻辑
你之前直接给tVecLogs赋值是无效的,JNI中传入的jobject是引用,需要调用Java的addAll方法将元素添加到传入的ArrayList实例中,而不是重新赋值。
3. 验证JNI方法签名的正确性
可以通过javah工具生成正确的JNI头文件,对比你的函数名和参数是否完全一致:
- 编译Java类后,执行命令:
javah -jni fxcl.hsm.log.TraceLog - 查看生成的头文件中的函数声明,确保你的JNI函数和头文件中的完全匹配(包括函数名、返回值、参数列表)
4. 检查其他可能的问题
- 确保编译JNI库时,使用的Java版本和运行时的Java版本一致
- 确保JNI库已经正确加载(Java端通过
System.loadLibrary加载) - 检查包名和类名是否完全匹配,JNI函数名中的
Java_fxcl_hsm_log_TraceLog_getLogs必须对应fxcl.hsm.log.TraceLog类下的getLogs方法
内容的提问来源于stack exchange,提问作者John Le
相关产品推荐
相关产品推荐

