永发信息网

如何使用C++程序运行一个jar文件

答案:1  悬赏:0  手机版
解决时间 2021-02-08 14:14
  • 提问者网友:谁的错
  • 2021-02-07 18:50
如何使用C++程序运行一个jar文件
最佳答案
  • 五星知识达人网友:毛毛
  • 2021-02-07 18:58
首先需要先加载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;
}
我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯