功能介绍
1. C++启动Java虚拟机
2. 通过C++指针调用main方法
环境
JDK: jdk-17.0.9
mingw-w64: x86_64-8.1.0-release-win32-seh-rt_v6-rev0
实现过程
1. 编写cpp程序
StartJVM.cpp
#include // JNI header provided by JDK
#include // C Standard IO Header
#include
int main() {
JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine)
JNIEnv *env; // Pointer to native interface
// JVM initialization arguments
JavaVMInitArgs vm_args;
JavaVMOption* options = new JavaVMOption[3];
options[0].optionString = (char*) "-Djava.class.path=D:/SDK/jdk-17.0.9/lib;."; // 设置你的类路径 (classpath),这里只是一个例子
options[1].optionString = (char*) "-Xmn512m";
options[2].optionString = (char*) "-Xmx1g";
// options[3].optionString = (char*) "-Djava.library.path=D:/SDK/jdk-17.0.9/bin";
vm_args.version = JNI_VERSION_10; // JVM version. This indicates version 1.6
vm_args.nOptions = 3;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
printf("JNI_CreateJavaVM %s\n", options[0].optionString);
HINSTANCE hVM = LoadLibrary("D:\\SDK\\jdk-17.0.9\\bin\\server\\jvm.dll");
if (hVM == NULL) {
printf("Load failed..");
}
typedef jint (CALLBACK *fpCJV)(JavaVM**, void**, JavaVMInitArgs*);
fpCJV CreateJavaVM = (fpCJV)GetProcAddress(hVM, "JNI_CreateJavaVM");
jint rc = CreateJavaVM(&jvm, (void**)&env, &vm_args);
// 加载并初始化一个JVM,"jvm"是返回的JVM接口的指针,"env"是返回的JNI接口的指针
//jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
printf("JNI_CreateJavaVM Finished!\n");
if (rc != JNI_OK) {
if (rc == JNI_EVERSION) {
fprintf(stderr, "FATAL ERROR: JVM is oudated and doesn't meet requirements");
}
else if (rc == JNI_ENOMEM) {
fprintf(stderr, "FATAL ERROR: Not enough memory for JVM");
}
else if (rc == JNI_EINVAL) {
fprintf(stderr, "FATAL ERROR: invalid ragument for launching JVM");
}
else if (rc == JNI_EEXIST) {
fprintf(stderr, "FATAL ERROR: the process can only launch one JVM an not multiple");
}
else {
fprintf(stderr, "FATAL ERROR: unknown error");
}
return rc;
}
else {
printf("JVM load succeeded. Version\n");
}
// 在这里你可以开始调用Java代码 ...
printf("可用调用Java了\n");
/* invoke the Main.test method using the JNI */
jclass cls = env->FindClass("JavaMain");
jmethodID mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
env->CallStaticVoidMethod(cls, mid, 100);
// 关闭JVM
jvm->DestroyJavaVM();
return 0;
}
JavaMain.java
public class JavaMain {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
System.out.println("I'm java");
}
}
2. 编译
编译cppg++ -Wall -g -I"D:\SDK\jdk-17.0.9\include" -I"D:\SDK\jdk-17.0.9\include\win32" -I"D:\SDK\jdk-17.0.9\include\win32\bridge" -L"D:\SDK\jdk-17.0.9\bin\server" -L"D:\SDK\jdk-17.0.9\bin" -L"D:\SDK\jdk-17.0.9\lib" -ljvm -fPIC StartJVM.cpp -o StartJVM.exe
参数说明:
-I 指定.h文件路径
-L 指定dll路径
-ljvm 加载jvm.dll
-o 输出路径
将JavaMain也编译到StartJVM.exe同目录, 最终效果