You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 11:15:01