调试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


浙公网安备 33010602011771号