初始化虚拟机
本地代码在调用Java方法之前必须先加载Java虚拟机,而后所有的Java程序都在虚拟机中执行。为了初始化Java虚拟机,JNI提供了一系列的接口函数Invocation API。通过这些API可以很方便地将虚拟机加载到内存中。
创建虚拟机可以用函数
jint JNI_CreateJavaVM
(JavaVM **pvm,
void **penv, void *args) |
对于这个函数有一点需要注意的是,在JDK 1.1中第三个参数总是指向一个结构JDK1_ 1InitArgs, 这个结构无法完全在所有版本的虚拟机中进行无缝移植。在JDK 1.2中已经使用了一个标准的初始化结构JavaVMInitArgs来替代JDK1_1InitArgs。下面我们分别给出两种不同版本的示例代码。
在JDK 1.1初始化虚拟机:
#include <jni.h>
int main() {
JNIEnv *env;
JavaVM *jvm;
JDK1_1InitArgs vm_args;
jint res;
/* IMPORTANT: 版本号设置一定不能漏 */
vm_args.version = 0x00010001;
/*获取缺省的虚拟机初始化参数*/
JNI_GetDefaultJavaVMInitArgs
(&vm_args);
/* 添加自定义的类路径 */
sprintf(classpath,
"%s%c%s",
vm_args.classpath,
PATH_SEPARATOR, USER_CLASSPATH);
vm_args.classpath = classpath;
/*设置一些其他的初始化参数*/
/* 创建虚拟机 */
res = JNI_CreateJavaVM
(&jvm,&env,&vm_args);
if (res < 0) {
fprintf(stderr,
"Can't create Java VM\n");
exit(1);
}
/*释放虚拟机资源*/
(*jvm)->DestroyJavaVM(jvm);
}
JDK 1.2初始化虚拟机:
/* invoke2.c */
#include <jni.h>
int main() {
int res;
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[3];
vm_args.version=JNI_VERSION_1_2;
//这个字段必须设置为该值
/*设置初始化参数*/
options[0].optionString
= "-Djava.compiler=NONE";
options[1].optionString
= "-Djava.class.path=.";
options[2].optionString
= "-verbose:jni";
//用于跟踪运行时的信息
/*版本号设置不能漏*/
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 3;
vm_args.options = options;
vm_args.ignoreUnrecognized
= JNI_TRUE;
res = JNI_CreateJavaVM(&jvm,
(void**)&env, &vm_args);
if (res < 0)
{
fprintf(stderr,
"Can't create Java VM\n");
exit(1);
}
(*jvm)->DestroyJavaVM(jvm);
fprintf(stdout,
"Java VM destory.\n");
} |
为了保证JNI代码的可移植性,建议使用JDK 1.2的方法来创建虚拟机。JNI_CreateJavaVM函数的第二个参数JNIEnv *env,就是贯穿整个JNI始末的一个参数,因为几乎所有的函数都要求一个参数就是JNIEnv *env。
访问类方法
初始化了Java虚拟机后,就可以开始调用Java的方法。要调用一个Java对象的方法必须经过几个步骤:
1.获取指定对象的类定义(jclass)
有两种途径来获取对象的类定义:第一种是在已知类名的情况下使用FindClass来查找对应的类。但是要注意类名并不同于平时写的Java代码,例如要得到类jni.test.Demo的定义必须调用如下代码:
jclass cls = (*env)->FindClass(env,
"jni/test/Demo");
//把点号换成斜杠 |
然后通过对象直接得到其所对应的类定义:
jclass cls = (*env)->
GetObjectClass(env, obj);
//其中obj是要引用的对象,
类型是jobject |
2.读取要调用方法的定义(jmethodID)
我们先来看看JNI中获取方法定义的函数:
jmethodID (JNICALL *GetMethodID)
(JNIEnv *env, jclass clazz,
const char *name,
const char *sig);
jmethodID (JNICALL *GetStaticMethodID)
(JNIEnv *env,
jclass class, const char
*name, const char *sig); | |