如何使用C++程序运行一个jar文件
发布网友
发布时间:2022-12-22 07:13
我来回答
共1个回答
热心网友
时间:2024-10-23 18:27
首先需要先加载JVM,然后根据jar中的函数签名寻找到相应的函数,然后运行相应的函数
一段样例代码如下
#include <iostream>
#include <jni.h>
#include <windows.h>
#include <cstring>
#include <direct.h>
using namespace std;
#define DIRLEN 10000
char* GetJrepath(int BIT);
int CallJAR(int BIT,char*buf,char*classPath,char*functionName);
int main(int argc, char *argv[])
{
char * buff = new char[DIRLEN];
getcwd(buff,DIRLEN);
strcat(buff,"\\lib\\support.jar");
if (argc<3)
{
cout<<"输入参数错误";
return 0;
}
int BIT = 32;
if(!strcmp(argv[2],"64"))
BIT = 64 ;
//-30 没有安装jre环境 -31 创建jvm失败 -32 缺少相关的库
if (!strcmp(argv[1],"0"))
{
//-20 配置文件错误 -21 JSON异常
return CallJAR(BIT,buff,"com/run/Author","StartAuthor");
}
else if(!strcmp(argv[1],"1"))
{
return CallJAR(BIT,buff,"com/run/UpdateStatus","UpdateStatus1");
}
else if(!strcmp(argv[1],"2"))
{
return CallJAR(BIT,buff,"com/run/SendMsg_webchinese","SendSMS");
}
else
{
return CallJAR(BIT,buff,"com/run/UpdateStatus","UpdateANDSMS");
}
}
char* GetJrepath(int BIT)
{
#define MYBUFF 123
HKEY hKey;
long lRet;
char* dir = new char[MYBUFF];
DWORD dwBufLen = MYBUFF;
char* s = new char[MYBUFF];
if(BIT == 64)
strcpy(s,"SOFTWARE\\Wow6432Node\\JavaSoft\\Java Runtime Environment\\");
else
strcpy(s,"SOFTWARE\\JavaSoft\\Java Runtime Environment\\");
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT((TCHAR*)s),
0,
KEY_QUERY_VALUE,
&hKey);
if(lRet!=ERROR_SUCCESS)
return NULL;
lRet = RegQueryValueEx(hKey,
TEXT((TCHAR*)"CurrentVersion"),
NULL,
NULL,
(LPBYTE)dir,
&dwBufLen);
RegCloseKey(hKey);
if(lRet!=ERROR_SUCCESS)
return NULL;
strcat(s,dir);
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT((TCHAR*)s),
0,
KEY_QUERY_VALUE,
&hKey);
if(lRet!=ERROR_SUCCESS)
return NULL;
dwBufLen = MYBUFF;
lRet = RegQueryValueEx(hKey,
TEXT((TCHAR*)"RuntimeLib"),
NULL,
NULL,
(LPBYTE)dir,
&dwBufLen);
RegCloseKey(hKey);
if(lRet!=ERROR_SUCCESS)
return NULL;
return dir;
}
int CallJAR(int BIT,char*buf,char*classPath,char*functionName)
{
typedef jint (WINAPI *PFunCreateJavaVM)(JavaVM **, void **, void *);
int res;
JavaVMInitArgs vm_args;
JavaVMOption options[3];
JavaVM *jvm;
JNIEnv *env;
int len =strlen("-Djava.class.path=.;")+strlen(buf)+20;
char* temp = new char[len];
strcpy(temp,"-Djava.class.path=.;");
strcat(temp,buf);
/*设置初始化参数*/
//disable JIT,这是JNI文档中的解释,具体意义不是很清楚 ,能取哪些值也不清楚。
//从JNI文档里给的示例代码中搬过来的
options[0].optionString = "-Djava.compiler=NONE";
//设置classpath,如果程序用到了第三方的JAR包,也可以在这里面包含进来
options[1].optionString = temp;
//设置显示消息的类型,取值有gc、class和jni,如果一次取多个的话值之间用逗号格开,如-verbose:gc,class
//该参数可以用来观察C++调用JAVA的过程,设置该参数后,程序会在标准输出设备上打印调用的相关信息
options[2].optionString = "-verbose:NONE";
//设置版本号,版本号有JNI_VERSION_1_1,JNI_VERSION_1_2和JNI_VERSION_1_4
//选择一个根你安装的JRE版本最近的版本号即可,不过你的JRE版本一定要等于或者高于指定的版本号
vm_args.version = JNI_VERSION_1_4;
vm_args.nOptions = 3;
vm_args.options = options;
//该参数指定是否忽略非标准的参数,如果填JNI_FLASE,当遇到非标准参数时,JNI_CreateJavaVM会返回JNI_ERR
vm_args.ignoreUnrecognized = JNI_TRUE;
//加载JVM.DLL动态库
HINSTANCE hInstance = ::LoadLibrary(GetJrepath(BIT));
if (hInstance == NULL)
{
return -30;
}
//取得里面的JNI_CreateJavaVM函数指针
PFunCreateJavaVM funCreateJavaVM = (PFunCreateJavaVM)::GetProcAddress(hInstance, "JNI_CreateJavaVM");
//调用JNI_CreateJavaVM创建虚拟机
res = (*funCreateJavaVM)(&jvm, (void**)&env, &vm_args);
if (res < 0)
{
return -31;
}
//查找test.Demo类,返回JAVA类的CLASS对象
jclass cls = env->FindClass(classPath);
//根据类的CLASS对象获取该类的实例
if (cls==0)
{
printf("FindClass failed\n");
(jvm)->DestroyJavaVM();
return -32;
}
jobject obj = env->AllocObject(cls);
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p -classpath 路径 文件名
jmethodID mid = env->GetMethodID(cls, functionName,"()I");
if (mid==0)
{
printf("getMethodID failed\n");
(jvm)->DestroyJavaVM();
return -32;
}
//构造参数并调用对象的方法
jstring msg = (jstring) env->CallObjectMethod(obj, mid);
//销毁虚拟机并释放动态库
jvm->DestroyJavaVM();
::FreeLibrary(hInstance);
return (int)msg;
}