文章目录
前言
前段时间公司因项目需要,需要使用C++调用jar包,但是网上的资料零零散散,完整的可借鉴的开发资料少之又少,于是就有了这篇文章, 把这段时间的开发的经验总结一下,以后,自己也可以回过头来温习一下,各位读者如果对调用流程不是很熟悉,只要细心的阅读,相信一定会有收获的。
一、说明
C++调用java的是通过加载java虚拟机来解释java字节码,然后再通过虚拟机来调用对应的java代码,
首先加载jvm库,只要安装了JDK都会有jvm库(动态库和静态库都有),加载流程如下
本文以动态库为实例
二、使用步骤
1.加载jvm动态库
代码如下(示例):
char szJVMpath[MAX_PATH] = {
0};
//通过环境变量javahome直接获取jvm.dll的路径,这里说明一下这个路径可以自己设置,不一定非要使用已经安装的jdk。
sprintf(szJVMpath, "%s\\jre\\bin\\server\\jvm.dll", getenv("JAVA_HOME"));
HINSTANCE hInstance = LoadLibrary(szJVMpath);
if (hInstance == NULL)
{
return false;
}
pFnCreateJavaVM m_CreateJavaVM = (pFnCreateJavaVM)GetProcAddress(hInstance, "JNI_CreateJavaVM");
pFnGetCreatedJavaVMs m_GetCreatedJavaVMs = (pFnGetCreatedJavaVMs)GetProcAddress(hInstance, "JNI_GetCreatedJavaVMs");
if (NULL == m_CreateJavaVM || NULL == m_GetCreatedJavaVMs)
{
return false;
}
2.创建虚拟机
代码如下(示例):
int ret = 0;
JavaVM* Tempjvm = NULL;
jsize count;
/*先获取当前进程中是否有已存在的jvm虚拟机, 如果存在则直接获取该虚拟机句柄, 如果不存在则创建新的虚拟机,
因为较新的jdk中一个进程中只允许存在创建一个虚拟机,如果当前进程中已存在虚拟机,重新调用m_CreateJavaVM接口创建虚拟机会失败。
如果你需要多线程使用虚拟机,则需要考虑这种情况, 因为虚拟机中 JavaVM虚拟机句柄是线程共享的 环境上下文env是非线程共享的
*/
ret = m_GetCreatedJavaVMs(&Tempjvm, sizeof(JavaVM) * 10, &count);
JNIEnv* env;
JavaVM* jvm;
if (0 == ret && NULL != Tempjvm && count > 0)
{
jvm = Tempjvm;
}
else
{
JavaVMInitArgs vm_args;
const int OPTION_COUNT = 5;
vm_args.nOptions = OPTION_COUNT;
JavaVMOption options[OPTION_COUNT] = {
0 };
char Currpath[256] = {
0};
int nCurrpathlen = 255;
getcwd(Currpath, nCurrpathlen);
char JarPath[256] = {
0};
char optionStringBuffer[1024] = {
0};
strcpy(JarPath, Currpath);
strcat(JarPath, "\\icbc-api-sdk-cop.zip");
char JarPath_io[256] = {
0};
strcpy(JarPath_io, Currpath);
strcat(JarPath_io, "\\icbc-api-sdk-cop-io.zip");
char JarPath_hsm[256] = {
0};
strcpy(JarPath_hsm, Currpath);
strcat(JarPath_hsm, "\\hsm-software-share-1.0.3.jar");
sprintf(optionStringBuffer, "-Djava.class.path=%s;%s;%s", JarPath, JarPath_io, JarPath_hsm);
//这里是设置需要加载的java文件,或者jar包,不同的源文件用;隔开即可。
options[0].optionString = optionStringBuffer;
/*这里是设置虚拟机的内存空间大小,vm虚拟机的内存 主要由三块构成(年轻代+老年代+持久代)
年轻代:所有新生成的对象都是放在年轻代中,年轻代的目的就是快速回收那些短生命周期的对象,年轻代分三个区,一个Edge区, 两个Survivor区域,大部分对象在Edge区生成,
当Edge区满了之后,虚拟机会将触发Scavenge GC,将edge还存活的对象移到Survivor区(两个其中的一个),当这个Survivor区满时