篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++调用JVM.dll运行Java程序,JNI实战简例,精简JRE实战相关的知识,希望对你有一定的参考价值。
精简一下JRE,实现C++和JAVA混合编程:
JRE目录:
jre/bin/server/jvm.dll
jre/bin/java.dll
jre/bin/verify.dll
jre/bin/zip.dll
jre/lib/rt.jar
下面是Java端测试内容:
jre/Test/com/hwb/Hello.java
1 2 3 4 5 6 7 8 9 | package com.hwb;
// public class Hello // public static void main(String[] args) System.out.println("Hello Java World!"); |
jre/Test/META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: 1.8.0_161 (Oracle Corporation)
Main-Class: com.hwb.Hello
jre/Test/Test.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import java.util.ArrayList; import java.util.HashMap; import java.util.Map;
// public class Test // public void Hello(String message) System.out.println("Hello in class Test, From c++ " + message);
// public static void main(String[] args) // System.out.println("Hello Java World!"); // //得到模板 TestFunction func = new TestFunction(); // Map<String, Object> params = new HashMap<String, Object>(); //测试参数 params.put("a", 1L); params.put("b", 2); params.put("c", new Long[]1L,2L,3L); //执行函数 Map<String,Object> output = func.apply(params); //遍历结果 for(Map.Entry<String, Object> entry : output.entrySet()) String mapKey = entry.getKey(); Object mapValue = entry.getValue(); System.out.println(mapKey + ":" + mapValue); |
jre/Test/TestFunction.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.function.Function;
//测试jdk1.8的Function特性 public class TestFunction implements Function<Map<String, Object>, Map<String, Object>> private static final String INPUT_VALUE = "input"; private static final String INPUT_STEP = "step"; private static final String INPUT_OFFSETS = "offsets"; private static final String INPUT_REVERSE = "reverse"; private static final String INPUT_BASE = "base"; private static final String OUTPUT_ISPASS = "isPass"; private static final String OUTPUT_RELEASE = "toRelease";
public TestFunction() //
//重写apply实现 public Map<String, Object> apply(Map<String, Object> param) HashMap output = new HashMap(); Long a = (Long)param.get("a"); int b = (Integer)param.getOrDefault("b", 0); if (output != null ) output.put("output", a+b); // Sum return output; else output.put("output", 0); return output; |
jre/Test/run.bat
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @echo off
set JAVA_HOME=C:\\Program Files\\Java\\jdk1.8.0_161 set PATH=%JAVA_HOME%/bin;%PATH% :: echo "--------------------java jar test----------------------" :: javac com/hwb/Hello.java java com.hwb.Hello :: jar -cvfm Hello.jar META-INF/MANIFEST.MF com/hwb/Hello.class java -jar Hello.jar
echo "------------------java Function test------------------------"
::javac PlanTemplateAlgorithm.java :: javac Test.java :: java Test
pause |
实战一下JNI编程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | // #include "Java/jni.h" #include <windows.h> #include <Shlwapi.h> #pragma comment(lib,"Shlwapi.lib") // #include <iostream> using namespace std;
//前置定义 bool CreateJvmAndTest();
//入口 int main(int argc, char* argv[]) cout << "Hello C++ JVM..." << endl; // CreateJvmAndTest(); //getchar(); return 0;
//构造函数 typedef jint(JNICALL *JNICREATEPROC)(JavaVM **, void **, void *);
//启动java虚拟机 bool CreateJvmAndTest() char exepath[1024] = 0 ; GetModuleFileNameA(nullptr, exepath, 1024); PathRemoveFileSpecA(exepath); //获取jvm动态库的路径 std::string jvmPath = std::string(exepath) + "\\\\..\\\\..\\\\jre\\\\bin\\\\server\\\\jvm.dll"; // //java虚拟机启动时接收的参数,每个参数单独一项 int nOptionCount = 2; JavaVMOption vmOption[2]; //设置JVM最大允许分配的堆内存,按需分配!!! vmOption[0].optionString = (char*)"-Xmx256M"; //设置classpath std::string classpath = std::string("-Djava.class.path=.\\\\;"); classpath += (std::string(exepath) + ";"); classpath += (std::string(exepath) + std::string("\\\\..\\\\..\\\\jre\\\\Test\\\\Hello.jar;")); classpath += (std::string(exepath) + std::string("\\\\..\\\\..\\\\jre\\\\Test\\\\;")); vmOption[1].optionString = (char*)classpath.c_str();
JavaVMInitArgs vmInitArgs; // vmInitArgs.version = JNI_VERSION_1_8;//JDK1.8版本 vmInitArgs.options = vmOption; vmInitArgs.nOptions = nOptionCount; // // 忽略无法识别jvm的情况 vmInitArgs.ignoreUnrecognized = JNI_TRUE;
//设置启动类,注意分隔符为"/" const char startClass[] = "com/hwb/Hello"; //启动方法,一般是main函数,当然可以设置成其他函数 const char startMethod[] = "main"; //加载JVM动态库 HINSTANCE jvmDLL = ::LoadLibraryA(jvmPath.c_str()); //加载失败的话:注意如果是64位jvm,就需要工程也是x64 if (jvmDLL == NULL) cout << "加载JVM动态库错误" + ::GetLastError() << endl; return false;
//获取JVM函数地址 JNICREATEPROC jvmProcAddress = (JNICREATEPROC)GetProcAddress(jvmDLL, "JNI_CreateJavaVM"); if (jvmDLL == NULL) FreeLibrary(jvmDLL); cout << "加载JVM动态库错误" + ::GetLastError() << endl; return false;
//创建JVM JNIEnv *env = nullptr; JavaVM *jvm = nullptr; jint jvmProc = (jvmProcAddress)(&jvm, (void **)&env, &vmInitArgs); if (jvmProc < 0 || jvm == nullptr || env == nullptr) FreeLibrary(jvmDLL); cout << "创建JVM错误" + ::GetLastError() << endl; return false;
//加载启动类 jclass mainclass = env->FindClass(startClass); if (env->ExceptionCheck() == JNI_TRUE || mainclass == nullptr) env->ExceptionDescribe(); env->ExceptionClear(); FreeLibrary(jvmDLL); cout << "加载启动类失败" << endl; return false;
//加载 main 启动方法 jmethodID methodID = env->GetStaticMethodID(mainclass, startMethod, "([Ljava/lang/String;)V"); if (env->ExceptionCheck() == JNI_TRUE || methodID == nullptr) env->ExceptionDescribe(); env->ExceptionClear(); FreeLibrary(jvmDLL); cout << "加载启动方法失败" << endl; return false;
cout << "开始执行" << endl; env->CallStaticVoidMethod(mainclass, methodID, nullptr); cout << "执行结束" << endl;
//测试JDK1.8函数编程 jclass funcClass = env->FindClass("Test"); if (env->ExceptionCheck() == JNI_TRUE || funcClass == nullptr) env->ExceptionDescribe(); env->ExceptionClear(); FreeLibrary(jvmDLL); cout << "加载Function类失败" << endl; return false;
//加载 main 启动方法 jmethodID funcMethodID = env->GetStaticMethodID(funcClass, startMethod, "([Ljava/lang/String;)V"); if (env->ExceptionCheck() == JNI_TRUE || funcMethodID == nullptr) env->ExceptionDescribe(); env->ExceptionClear(); FreeLibrary(jvmDLL); cout << "加载启动方法失败" << endl; return false;
cout << "开始执行" << endl; env->CallStaticVoidMethod(funcClass, funcMethodID, nullptr); cout << "执行结束" << endl;
cout << "开始执行类对象方法" << endl; //调用成员方法 jobject string_object = env->AllocObject(funcClass);//创建类对象 // jmethodID paramMethodID = env->GetMethodID(funcClass, "Hello", "(Ljava/lang/String;)V");//查找类方法【void Hello(String msg)】 // jstring param = env->NewStringUTF("hello"); env->CallVoidMethod(string_object, paramMethodID, param);//执行对象方法 // cout << "执行结束类对象方法" << endl;
//jvm释放 jvm->DestroyJavaVM(); FreeLibrary(jvmDLL);
return true; |
运行结果:
Hello C++ JVM...
开始执行
Hello Java World!
执行结束
开始执行
Hello Java World!
output:3
执行结束
开始执行类对象方法
Hello in class Test, From c++ hello
执行结束类对象方法