调试jni的java代码

java代码

public class HelloJava {
    // 供C++调用的静态方法示例
    public static String concatStrings(String str1, String str2) {
        System.out.println("[Java] 方法 concatStrings 被调用,参数: \"" + str1 + "\", \"" + str2 + "\"");
        return str1 + " + " + str2 + " (来自Java的拼接)";
    }

    // 供C++调用的实例方法示例
    public String greet(String name) {
        String greeting = "Hello, " + name + "!";
        System.out.println("[Java] 实例方法 greet 被调用,返回: " + greeting);
        return greeting;
    }

    // 主方法,仅用于独立测试这个Java类
    public static void main(String[] args) {
        HelloJava hello = new HelloJava();
        System.out.println("测试静态方法: " + concatStrings("Hello", "World"));
        System.out.println("测试实例方法: " + hello.greet("JNI"));
    }
}

cpp_caller.cpp

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

int main() {
    // ==================== 第一部分:准备 & 启动JVM ====================
    JavaVM *jvm;                 // JVM 指针
    JNIEnv *env;                 // JNI 环境指针,用于调用大多数JNI函数
    JavaVMInitArgs vm_args;      // JVM 启动参数

    JavaVMOption options[4];     // JVM 选项数组

    // 设置JVM的classpath,关键!必须包含你的Java类所在的路径。
    // **重要**:请将 `/path/to/your/classes` 替换为你编译后的 HelloJava.class 文件所在的实际目录。
    // 例如: "C:/myproject/classes" 或 "/home/user/myproject/classes"
    // 在 classpath 中包含当前目录 (.) 通常是个好习惯。
    std::string classPathOption = "-Djava.class.path=./:/path/to/your/classes";
    options[0].optionString = const_cast<char *>(classPathOption.c_str());

    // 其他可选参数:关闭JIT编译,有时对调试有帮助(非必需)。
    options[1].optionString = const_cast<char *>("-Xint");
    // 设置JVM最大堆内存(可选)
    options[2].optionString = const_cast<char *>("-Xmx128M");
    options[3].optionString = const_cast<char *>("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005");

    vm_args.version = JNI_VERSION_1_8; // 根据你的JDK版本设置,1.8或更高
    vm_args.nOptions = 4;
    vm_args.options = options;
    vm_args.ignoreUnrecognized = JNI_TRUE; // 忽略无法识别的参数

    // 创建JVM
    jint res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
    if (res != JNI_OK) {
        std::cerr << "[C++] 创建JVM失败!错误代码: " << res << std::endl;
        return 1;
    }
    std::cout << "[C++] JVM 启动成功。" << std::endl;

    // ==================== 第二部分:调用Java静态方法 ====================
    std::cout << "\n[C++] === 开始调用Java静态方法 ===" << std::endl;

    // 1. 查找并加载Java类
    jclass helloJavaClass = env->FindClass("HelloJava");
    if (helloJavaClass == nullptr) {
        std::cerr << "[C++] 找不到 'HelloJava' 类。请检查classpath设置。" << std::endl;
        jvm->DestroyJavaVM();
        return 1;
    }

    // 2. 获取静态方法ID (方法名, 签名)
    // 方法签名: `(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;`
    // 表示:参数为两个String,返回值为一个String
    jmethodID staticMethodId = env->GetStaticMethodID(helloJavaClass,
                                                      "concatStrings",
                                                      "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
    if (staticMethodId == nullptr) {
        std::cerr << "[C++] 找不到静态方法 'concatStrings'。" << std::endl;
        jvm->DestroyJavaVM();
        return 1;
    }

    // 3. 准备参数(将C++字符串转换为Java字符串)
    jstring javaArg1 = env->NewStringUTF("你好");
    jstring javaArg2 = env->NewStringUTF("世界");

    // 4. 调用静态方法
    jstring javaStaticResult = (jstring)env->CallStaticObjectMethod(helloJavaClass,
                                                                    staticMethodId,
                                                                    javaArg1,
                                                                    javaArg2);

    // 5. 处理结果(将Java字符串转换为C++字符串)
    const char *cStaticResult = env->GetStringUTFChars(javaStaticResult, nullptr);
    std::cout << "[C++] 收到Java静态方法的返回值: " << cStaticResult << std::endl;

    // 6. 释放局部引用和字符串内存
    env->ReleaseStringUTFChars(javaStaticResult, cStaticResult);
    env->DeleteLocalRef(javaArg1);
    env->DeleteLocalRef(javaArg2);
    env->DeleteLocalRef(javaStaticResult);

    // ==================== 第三部分:调用Java实例方法 ====================
    std::cout << "\n[C++] === 开始调用Java实例方法 ===" << std::endl;

    // 1. 获取构造方法ID (默认构造方法)
    jmethodID constructorId = env->GetMethodID(helloJavaClass, "<init>", "()V");
    if (constructorId == nullptr) {
        std::cerr << "[C++] 找不到HelloJava的构造方法。" << std::endl;
        jvm->DestroyJavaVM();
        return 1;
    }

    // 2. 创建Java对象实例
    jobject helloJavaObject = env->NewObject(helloJavaClass, constructorId);
    if (helloJavaObject == nullptr) {
        std::cerr << "[C++] 创建HelloJava对象失败。" << std::endl;
        jvm->DestroyJavaVM();
        return 1;
    }

    // 3. 获取实例方法ID
    jmethodID instanceMethodId = env->GetMethodID(helloJavaClass,
                                                  "greet",
                                                  "(Ljava/lang/String;)Ljava/lang/String;");
    if (instanceMethodId == nullptr) {
        std::cerr << "[C++] 找不到实例方法 'greet'。" << std::endl;
        jvm->DestroyJavaVM();
        return 1;
    }

    // 4. 准备参数并调用实例方法
    jstring javaNameArg = env->NewStringUTF("程序员");
    jstring javaInstanceResult = (jstring)env->CallObjectMethod(helloJavaObject,
                                                                instanceMethodId,
                                                                javaNameArg);

    // 5. 处理结果
    const char *cInstanceResult = env->GetStringUTFChars(javaInstanceResult, nullptr);
    std::cout << "[C++] 收到Java实例方法的返回值: " << cInstanceResult << std::endl;

    // 6. 释放资源
    env->ReleaseStringUTFChars(javaInstanceResult, cInstanceResult);
    env->DeleteLocalRef(javaNameArg);
    env->DeleteLocalRef(javaInstanceResult);
    env->DeleteLocalRef(helloJavaObject);
    env->DeleteLocalRef(helloJavaClass); // 类引用也建议释放

    // ==================== 第四部分:关闭JVM ====================
    std::cout << "\n[C++] 调用完成,正在关闭JVM..." << std::endl;
    jvm->DestroyJavaVM();
    std::cout << "[C++] 程序结束。" << std::endl;
    return 0;
}

 

javac HelloJava.java 

g++ -o cpp_caller     -I"$JAVA_HOME/include"     -I"$JAVA_HOME/include/linux"     cpp_caller.cpp     -L"$JAVA_HOME/lib/server"     -ljvm     -Wl,-rpath,$JAVA_HOME/lib/server

./cpp_caller

image

 

posted @ 2026-01-07 21:26  stupidstan2019  阅读(9)  评论(0)    收藏  举报