简单的C++加载jvm实现

以前由于忙一直没有时间静下心来把学到的东西进行归纳整理,最近由于某些原因,总算可以总结一下了。


该小功能为大功能的前置部分,整个小功能需要用到windowService,主体逻辑主要使用java,故需要使用到C++加载jvm的技术,下面进入正题。


一,创建一个简单的java程序

package test;
public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("Hello world");
	}
}
导出成Helloworld.jar


二,收集必要的一些资源文件

1,找到jvm,windows平台下jdk的java虚拟机动态库为jvm.dll,位于:
%JAVA_HOME%/jre/bin/client/jvm.dll
%JAVA_HOME%/jre/bin/server/jvm.dll

注:64x系统下没有client路径下的jvm。

2,获得jni.h和jni_md.h,位于

%JAVA_HOME%/include/jni.h

%JAVA_HOME%/include/win32/jni_md.h


三,创建一个简单的C++工程,将上面的文件都放入编译目录下


工程的编码如下:

#include "stdafx.h"
#include "jni.h"

using namespace std;

bool startJVM();

int _tmain(int argc, _TCHAR* argv[])
{
	cout<<"haha"<<endl;
	startJVM();
	return 0;
}

typedef jint(JNICALL *JNICREATEPROC)(JavaVM **, void **, void *);
//设置输出流
bool setStream(JNIEnv *env, const char* fileName, const char* method);

//启动java虚拟机

bool startJVM(){
	//获取jvm动态库的路径
	TCHAR* jvmPath = _T("E://eclipse-jee-kepler-SR2-win32//Java//jre//bin//client//jvm.dll");

	//java虚拟机启动时接收的参数,每个参数单独一项
	int nOptionCount = 2;
	JavaVMOption vmOption[2];
	//设置JVM最大允许分配的堆内存,按需分配
	vmOption[0].optionString = "-Xmx256M";
	//设置classpath
	vmOption[1].optionString = "-Djava.class.path=./HelloWorld.jar";

	JavaVMInitArgs vmInitArgs;
	vmInitArgs.version = JNI_VERSION_1_6;
	vmInitArgs.options = vmOption;
	vmInitArgs.nOptions = nOptionCount;
	//忽略无法识别jvm的情况
	vmInitArgs.ignoreUnrecognized = JNI_TRUE;

	//设置启动类,注意分隔符为"/"
	const char startClass[] = "test/HelloWorld";
	//启动方法,一般是main函数,当然可以设置成其他函数
	const char startMethod[] = "main";

	//加载JVM,注意需要传入的字符串为LPCWSTR,指向一个常量Unicode字符串的32位指针,相当于const wchar_t*
	HINSTANCE jvmDLL = LoadLibrary(jvmPath);
	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;
	JavaVM *jvm;
	jint jvmProc = (jvmProcAddress)(&jvm, (void **)&env, &vmInitArgs);
	if(jvmProc < 0 || jvm == NULL ||env == NULL){
		FreeLibrary(jvmDLL);
		cout<<"创建JVM错误"+ ::GetLastError()<<endl;
		return false;
	}

	//加载启动类
	jclass mainclass = env ->FindClass(startClass);
	if(env -> ExceptionCheck() == JNI_TRUE || mainclass == NULL){
		env -> ExceptionDescribe();
		env -> ExceptionClear();
		FreeLibrary(jvmDLL);
		cout<<"加载启动类失败"<<endl;
		return false;
	}

	//加载启动方法
	jmethodID methedID = env ->GetStaticMethodID(mainclass, startMethod, "([Ljava/lang/String;)V");
	if(env -> ExceptionCheck() == JNI_TRUE || methedID == NULL){
		env -> ExceptionDescribe();
		env -> ExceptionClear();
		FreeLibrary(jvmDLL);
		cout<<"加载启动方法失败"<<endl;
		return false;
	}
	
	cout<<"开始执行"<<endl;
	env ->CallStaticVoidMethod(mainclass, methedID, NULL);
	cout<<"执行结束"<<endl;

	//jvm释放
	jvm -> DestroyJavaVM();
	return true;
}
编译的过程中需要注意的是,如果是64位的系统需要将工程的解决方案改成64x的,不然无法加载jvm,在
	HINSTANCE jvmDLL = LoadLibrary(jvmPath);
这一步取不到结果。


四,运行结果如下



  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值