C++使用Jni调用jar包

        首先自己编译包(开始的时候使用idea编译的出jar包,但在使用Jni的findClass始终拿不到类对象,因而手动编译)
创建一个Java程序如下(Test.java):

public class Test {
    public String SayHello()
    {
        return "Hello";
    }
}

使用命令行:javac Test.java(自行配置jdk环境变量)

根据不同需要给出一下命令行:

javac -encoding utf-8 xxx.java   #解决编码问题,utf-8可以修改成所需编码
javac -classpath:xxx.jar xxx.java  #存在jar包链接的情况使用,多个用;分割

执行且未报错后在当前目录可以看到生成了XXX.class文件

。。。

查看方法的签名:

javap -s -p -classpath XXX XXX.class

可以得到如下签名,在后续调用时xu'yao

可以看到函数的签名

准备工作做完,接下来实现jar的调用

使用C++调用Jni代码如下:

#include "stdafx.h"
#include "CJavaJni.h"

CJavaJni::CJavaJni()
{

}

CJavaJni::~CJavaJni()
{

}

/*C字符串转JNI字符串*/
jstring stoJstring(JNIEnv* env, const char* pat) {
    jclass strClass = (env)->FindClass("Ljava/lang/String;");
    jmethodID ctorID = (env)->GetMethodID(strClass, "<init>",
        "([BLjava/lang/String;)V");
    jbyteArray bytes = (env)->NewByteArray(strlen(pat));
    (env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);
    jstring encoding = (env)->NewStringUTF("utf-8");
    return (jstring)(env)->NewObject(strClass, ctorID, bytes,
        encoding);
}
/*JNI字符串转C字符串*/
char* jstringTostring(JNIEnv* env, jstring jstr) {
    char* rtn = NULL;
    jclass clsstring = (env)->FindClass("java/lang/String");
    jstring strencode = (env)->NewStringUTF("utf-8");
    jmethodID mid = (env)->GetMethodID(clsstring, "getBytes",
        "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray)(env)->CallObjectMethod(jstr, mid,
        strencode);
    jsize alen = (env)->GetArrayLength(barr);
    jbyte* ba = (env)->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char*)malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    (env)->ReleaseByteArrayElements(barr, ba, 0);
    return rtn;
}

jobject setHashMAp(JNIEnv* env, map<int, vector<char>> mMap) {
    jclass hashMapClass = env->FindClass("java/util/HashMap");
    jmethodID hashMapInit = env->GetMethodID(hashMapClass, "<init>", "(I)V");
    jobject hashMapObj = env->NewObject(hashMapClass, hashMapInit, mMap.size());
    jmethodID hashMapOut = env->GetMethodID(hashMapClass, "put",
        "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");

    for (auto it : mMap)
    {
        char* data = (char*)malloc(it.second.size());
        for (size_t i = 0; i < it.second.size(); i++)
        {
            data[i] = it.second[i];
        }
        jbyte* by = (jbyte*)data;
        jbyteArray jarray = env->NewByteArray(it.second.size());
        env->SetByteArrayRegion(jarray, 0, it.second.size(), by);
        jobject dataint = (jobject)(jint)it.first;

        env->CallObjectMethod(hashMapObj, hashMapOut,
            env->NewStringUTF(to_string(it.first).c_str()),
            jarray);

        free(data);
    }

    env->PopLocalFrame(hashMapObj);

    return hashMapObj;
}

void init(JNIEnv* env, jclass cls, jobject& obj, const char* pPsdzRootDirectoryName, const char* pSecurityDirectoryName)
{
    /*获取构造函数,用于创建对象*/
    /***1.1可用""作为构造函数, 1.2用"<init>"参数中不能有空格
    "(Ljava/lang/String;)V"*/
    jmethodID mid = (env)->GetMethodID(cls, "init",
        "(Ljava/lang/String;Ljava/lang/String;)V");
    if (mid == 0) {
        fprintf(stderr, "GetMethodID failed\n");
        //(jvm)->DestroyJavaVM();
        fprintf(stdout, "Java VM destory.\n");
        return;
    }
    fprintf(stdout, "ok 获取类中的方法\n");

    //构造参数并调用对象的方法  
    jstring fpdm = stoJstring(env, pPsdzRootDirectoryName);

    jstring fphm = stoJstring(env, pSecurityDirectoryName);

    (env)->CallObjectMethod(obj, mid, fpdm, fphm);

    return;
}


int CJavaJni::openJVM()
{
    LPCWSTR szJVMpath = L"C:\\Program Files\\Eclipse Foundation\\jdk-8.0.302.8-hotspot\\jre\\bin\\server\\jvm.dll";
    //CString
    HINSTANCE hInstance = LoadLibrary(szJVMpath);
    if (hInstance == NULL)
    {
        return false;
    }

    typedef jint(JNICALL* CreateJavaVMFuncPtr)(JavaVM** pvm, void** penv, void* args);
    CreateJavaVMFuncPtr CreateJavaVM = (CreateJavaVMFuncPtr)GetProcAddress(hInstance, "JNI_CreateJavaVM");
    JavaVMInitArgs vm_args;
    JavaVMOption options[3];
    /*设置初始化参数*/
    //F:\\bmw\\bmwjar\\bmw-security.jar;
    //:F:\\bmw\\bmwjar\\commons-io-2.5.jar:F:\\bmw\\bmwjar\\dom4j-1.5.jar:F:\\bmw\\bmwjar\\iaik-eccelerate-5.0.jar:F:\\bmw\\bmwjar\\iaik-jce-full-5.52.jar:F:\\bmw\\bmwjar\\log4j-1.2.17.jar
    options[0].optionString = (char*)"-Djava.compiler=NONE";
    options[1].optionString = (char*)"-Djava.class.path=F:\\bmw\\bmwjar\\bmw-security.jar;F:\\bmw\\bmwjar\\commons-io-2.5.jar;F:\\bmw\\bmwjar\\dom4j-1.5.jar;F:\\bmw\\bmwjar\\iaik-eccelerate-5.0.jar;F:\\bmw\\bmwjar\\iaik-jce-full-5.52.jar;F:\\bmw\\bmwjar\\log4j-1.2.17.jar;";  //这里指定了要使用的第三方Jar包
    options[2].optionString = (char*)"-verbose:NONE"; //用于跟踪运行时的信息

    /*版本号设置不能漏*/
    vm_args.version = JNI_VERSION_1_6;//jdk版本目前有1.1,1.2,1.4 只要比你的jdk的版本低就可以
    vm_args.nOptions = 3;
    vm_args.options = options;
    vm_args.ignoreUnrecognized = JNI_TRUE;

    jint res = (*CreateJavaVM)(&jvm, (void**)&env, &vm_args);
    if (res < 0)
    {
        return false;
    }

    return true;
}

int CJavaJni::LoadAuSSecurityDeal()
{
    /*获取实例的类定义*/
    cls = (env)->FindClass("AuSSecurityDeal");    //这里是jar包内AuSSecurityDeal类的具体路径
    if (cls == 0) {
        (jvm)->DestroyJavaVM();
        return -1;
    }

    /*创建对象实例*/
    obj = (env)->AllocObject(cls);
    if (obj == NULL) {
        fprintf(stderr, "AllocObject failed\n");
        (jvm)->DestroyJavaVM();
        fprintf(stdout, "Java VM destory.\n");
        return -1;
    }
    fprintf(stdout, "ok 获取该类的实例\n");
    init(env, cls, obj, "F:\\bmw", "bmwjar\\");

    return 0;
}

int CJavaJni::calSecurity(char* calSec, jint lev, jbyteArray jbyteData, jstring js)
{
    jmethodID mid = env->GetMethodID(cls, "calSecurity",
        "(I[BLjava/lang/String;)[B");
    if (mid == 0) {
        return 0;
    }

    jbyteArray barr = (jbyteArray)(env)->CallObjectMethod(obj, mid, lev, jbyteData, js);
    char* rtn = NULL;

    jsize alen = (env)->GetArrayLength(barr);
    jbyte* ba = (env)->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0) {
        //rtn = (char*)malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }

    return alen;
}

int CJavaJni::signCodingData(char* calSig, jobject mUserData, jint iTLIDblockAddr, jstring pBootloaderID)
{
    jmethodID mid = (env)->GetMethodID(cls, "signCodingData",
        "(Ljava/util/Map;ILjava/lang/String;)[B");
    if (mid == 0) {
        //(jvm)->DestroyJavaVM();
        return 0;
    }

    jbyteArray barr = (jbyteArray)(env)->CallObjectMethod(obj, mid, mUserData, iTLIDblockAddr, pBootloaderID);
    jsize alen = (env)->GetArrayLength(barr);
    jbyte* ba = (env)->GetByteArrayElements(barr, JNI_FALSE);
    char* rtn = NULL;
    if (alen > 0) {
        //rtn = (char*)malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }

    return alen;
}

int CJavaJni::DestroyJavaVM()
{
    /*捕捉异常*/
    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
        return -1;
    }
    /*销毁JAVA虚拟机*/
    jvm->DestroyJavaVM();

    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值