JNI调用Class.forName时CallStaticObjectMethod段错误问题求助
问题根因
你触发段错误的核心问题是:JNI调用Java方法时,必须传入JNI规范定义的对应类型参数,你直接将C原生字符串 char* 传递给了要求 java.lang.String 类型的forName方法,JVM会把C字符串的内存地址当成Java String对象的引用访问,直接触发非法内存访问崩溃。
修复方案
在调用CallStaticObjectMethod前,先将C字符串转换为JNI的jstring类型对象,再作为参数传入即可。
修复后的test.c核心代码段如下:
#include <jni.h> JNIEXPORT jobject JNICALL Java_Test_test(JNIEnv *env, jobject thiz) { const char* out = "success"; do { jclass cls_cls = (*env)->FindClass(env, "java/lang/Class"); if ( !cls_cls ) { out = "FindClass"; break; } jmethodID mfn = (*env)->GetStaticMethodID( env, cls_cls, "forName", "(Ljava/lang/String;)Ljava/lang/Class;" ); if ( !mfn ) { out = "GetStaticMethodID"; break; } // 先将C字符串转为jstring类型的JNI对象 jstring strClzName = (*env)->NewStringUTF(env, "java.lang.String"); if (!strClzName) { out = "NewStringUTF"; break; } // 传入jstring对象,而非原生C字符串 jclass cls = (jclass) (*env)->CallStaticObjectMethod( env, cls_cls, mfn, strClzName ); // 用完主动释放局部引用,避免局部引用表溢出(也可以等方法返回自动释放) (*env)->DeleteLocalRef(env, strClzName); if ( (*env)->ExceptionCheck(env) ) { out = "CallStaticObjectMethod"; break; } // 后续逻辑可自行处理拿到的cls对象 } while ( 0 ); (*env)->ExceptionClear(env); return (jobject) (*env)->NewStringUTF(env, out); }
额外注意点
- 所有JNI调用中涉及Java侧的
String参数,都必须使用NewStringUTF等JNI接口转换原生字符串为jstring类型后再传递 - 不需要继续使用的局部JNI引用(比如示例中的
cls_cls、cls、strClzName)建议主动调用DeleteLocalRef释放,避免局部引用表占用过多
内容的提问来源于stack exchange,提问作者AndyT
相关产品推荐
相关产品推荐

