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

JNI无法从Jar文件中查找类问题求助

解决JNI从Jar文件查找类返回nullptr的问题

问题根源分析

你的代码里有两个关键错误导致Jar包未被正确加入类路径:

  1. nOptions参数设置错误
    你创建了1个JavaVMOption实例,但vm_args.nOptions被设为0,JVM会忽略传入的options数组,自然不会加载指定的Jar包。

  2. memset使用错误
    memset(options[0].optionString, sizeof(options[0].optionString), 0) 这行代码存在两个问题:

    • memset的参数顺序是(目标地址, 填充值, 字节数),你把填充值和字节数搞反了
    • sizeof(options[0].optionString)获取的是指针的大小(32位系统为4,64位为8),不是你分配的数组长度,应该用strlen(jar_path) + 1

修正后的代码

#include <jni.h>
#include <iostream>
#include <cstring>

using namespace std;

int main(int argc, char** argv) {
    JavaVM* jvm = nullptr;
    JNIEnv* env = nullptr;

    JavaVMInitArgs vm_args;
    JavaVMOption* options = new JavaVMOption[1];
    const char* jar_path = R"(-Djava.class.path=.;.\MyTest.jar)";
    // 分配内存并直接复制路径,替代容易出错的memset+memcpy
    options[0].optionString = new char[strlen(jar_path) + 1];
    strcpy(options[0].optionString, jar_path);

    vm_args.version = JNI_VERSION_1_8;
    vm_args.nOptions = 1; // 对应创建的1个选项
    vm_args.options = options;
    vm_args.ignoreUnrecognized = false;

    jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
    // 释放optionString的内存,避免泄漏
    delete[] options[0].optionString;
    delete[] options;

    if (rc != JNI_OK) {
        cout << "Error code : " << rc;
        cin.get();
        exit(EXIT_FAILURE);
    }

    cout << "JVM load succeeded: Version ";
    jint ver = env->GetVersion();
    cout << ((ver >> 16) & 0x0f) << "." << (ver & 0x0f) << endl;

    jclass cls = env->FindClass("MyTest");
    if (cls != nullptr) {
        cout << "Success" << endl;
        // 可选:调用类的静态方法验证加载成功
        jmethodID mid = env->GetStaticMethodID(cls, "mymain", "()V");
        if (mid != nullptr) {
            env->CallStaticVoidMethod(cls, mid);
        }
    }
    else {
        cout << "Failed" << endl;
        // 打印JVM异常信息,辅助排查其他问题
        jthrowable exc = env->ExceptionOccurred();
        if (exc) {
            env->ExceptionDescribe();
            env->ExceptionClear();
        }
    }

    jvm->DestroyJavaVM();
    cin.get();
}

额外优化建议

  • 用strcpy替代memset+memcpy,代码更简洁且不易出错
  • 记得释放options[0].optionString的内存,避免内存泄漏
  • 当FindClass失败时,调用ExceptionOccurred()和ExceptionDescribe()可以查看JVM抛出的具体错误信息,方便排查类路径相关的其他问题

验证步骤

  1. 编译修正后的C++代码
  2. 确保MyTest.jar位于程序运行目录下
  3. 运行程序,应输出Success并调用mymain方法打印Java端的内容

内容的提问来源于stack exchange,提问作者pswgoo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:22:52