#include <stdio.h>
#include <jni.h>
#include <string.h>
/*创建Java Virtual Machine, 其中唯一一个Option的值为jar包所在位置。其中路径分隔符在Win32下为“;”, Linux下为“:”*/
JNIEnv* create_vm(JavaVM ** jvm) {
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options;
options.optionString =
"-Djava.class.path=.;E:\\xx\\DemoDemo.jar"
;
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = &options;
vm_args.ignoreUnrecognized = 0;
int
ret = JNI_CreateJavaVM(jvm, (
void
**)&env, &vm_args);
if
(ret < 0)
printf
(
"\nUnable to Launch JVM\n"
);
return
env;
}
int
main(
int
argc,
char
* argv[])
{
printf
(
"main start\n"
);
JNIEnv *env;
JavaVM * jvm;
env = create_vm(&jvm);
if
(env == NULL)
{
printf
(
"JVM NULL\n"
);
return
1;
}
//预先准备DemoDemo类的引用,以及Demo对象的引用
jclass jcHBaseAbstractLayer = NULL;
jclass jcEntity = NULL;
jobject jobDemo = NULL;
jobject jobEntity = NULL;
//声明所需方法的引用
//其中jmiHBaseAbstractLayerCons为类的默认构造函数
//jmiDemo为Demo函数,jmiListGet为getString函数jmiListSize为getSize函数
//jmethodID jmiDemoCons = NULL;
jmethodID jmiHBaseAbstractLayerCons = NULL;
jmethodID jmiDemo = NULL;
jmethodID jmiListGet = NULL;
jmethodID jmiListSize = NULL;
jmethodID jmiDisplayEntity = NULL;
//1. 寻找类,FindClass com/demo/DemoDemo, 包.类 分隔符用“/”
jcHBaseAbstractLayer = (*env)->FindClass(env,
"com/demo/DemoDemo"
);
jcEntity = (*env)->FindClass(env,
"com/demo/Entity"
);
if
(jcHBaseAbstractLayer != NULL || jcEntity == NULL)
{
/*2. 找到所需要的方法,参数是静态方法则使用函数GetStaticMethodID获取ID*/
jmiDemo = (*env)->GetMethodID(env, jcHBaseAbstractLayer,
"Demo"
,
"()Ljava/lang/String;"
);
jmiListGet = (*env)->GetMethodID(env, jcHBaseAbstractLayer,
"getString"
,
"(I)Ljava/lang/String;"
);
jmiListSize = (*env)->GetMethodID(env, jcHBaseAbstractLayer,
"getSize"
,
"()I"
);
jmiDisplayEntity = (*env)->GetMethodID(env, jcHBaseAbstractLayer,
"displayEntity"
,
"(Lcom/demo/Entity;)V"
);
if
(jmiDemo == NULL)
printf
(
"jmiDemo\n"
);
if
(jmiListSize == NULL)
printf
(
"jmiListSize\n"
);
if
(jmiListGet == NULL)
printf
(
"jmiListGet\n"
);
if
(jmiDisplayEntity == NULL)
printf
(
"jmiDisplayEntity\n"
);
//3. 生成对象,此处有两种方法生成对象,第二种可以指定构造函数
//jobDemo = (*env)->AllocObject(env, jcHBaseAbstractLayer);
jmiHBaseAbstractLayerCons = (*env)->GetMethodID(env, jcHBaseAbstractLayer,
"<init>"
,
"()V"
);
jobDemo = (*env)->NewObject(env, jcHBaseAbstractLayer, jmiHBaseAbstractLayerCons);
if
(jobDemo == NULL)
printf
(
"jobDEMOERROR\n"
);
/*4 .调用对应方法,若是静态方法可直接调用而不需生成对象,使用CallStaticObjectMethod函数调用。参数依次是 jvm环境,对象引用,方法引用,即调用某jvm下的某object的某方法。起返回值基本是jint,jstring或者jobject之类。其中jstring需要调用函数来转换成C风格字符串,最后还需释放。*/
jstring result = (jstring)(*env)->CallObjectMethod(env, jobDemo, jmiDemo);
const
char
* str = (*env)->GetStringUTFChars(env, result, 0);
printf
(
"Result : %s\n"
, str);
(*env)->ReleaseStringUTFChars(env, result, 0);
jint x = (jint)(*env)->CallObjectMethod(env, jobDemo, jmiListSize);
printf
(
"LENGTH: %d\n"
, (
int
)x);
//直接获取对象属性,似乎不受Java访问保护的限制。同时类似的有SetObjectField函数来设置对象属性。
jint c = (jint)(*env)->GetIntField(env, jobDemo, (*env)->GetFieldID(env, jcHBaseAbstractLayer,
"size"
,
"I"
));
printf
(
"XXXXXXXXXX: %d\n"
, (
int
)c);
for
(
int
p = 0; p < x; ++p)
{
jstring res = (jstring)(*env)->CallObjectMethod(env, jobDemo, jmiListGet, p);
const
char
* str1 = (*env)->GetStringUTFChars(env, res, 0);
printf
(
"PResult : %s\n"
, str1);
(*env)->ReleaseStringUTFChars(env, res, 0);
}
//SetObjectField 测试新建一个对象并设置属性并当做参数传入所需的方法,并调用该方法
jobEntity = (*env)->AllocObject(env, jcEntity);
(*env)->SetObjectField(env, jobEntity, (*env)->GetFieldID(env, jcEntity,
"name"
,
"Ljava/lang/String;"
), (*env)->NewStringUTF(env,
"Zirconi"
));
(*env)->SetIntField(env, jobEntity, (*env)->GetFieldID(env, jcEntity,
"age"
,
"I"
), (jint)19);
(*env)->CallObjectMethod(env, jobDemo, jmiDisplayEntity, jobEntity);
}
else
{
printf
(
"FINDERROR\n"
);
(*jvm)->DestroyJavaVM(jvm);
}
(*jvm)->DestroyJavaVM(jvm);
return
0;
}