精简一下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
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
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 params = new HashMap();
//测试参数
params.put("a", 1L);
params.put("b", 2);
params.put("c", new Long[]{1L,2L,3L});
//执行函数
Map output = func.apply(params);
//遍历结果
for(Map.Entry entry : output.entrySet()){
String mapKey = entry.getKey();
Object mapValue = entry.getValue();
System.out.println(mapKey + ":" + mapValue);
}
}
}
jre/Test/TestFunction.java
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
jre/Test/run.bat
@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 TestFunction.java
::
javac Test.java
::
java Test
pause
实战一下JNI编程:
//
#include "Java/jni.h"
#include
#include
#pragma comment(lib,"Shlwapi.lib")
//
#include
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
执行结束类对象方法
over......