首先自己编译包(开始的时候使用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;
}