#include //jni的主要头文件
//函数名字可以随便取,不过参数一定要和javah生成的函数的参数一致,包括返回值
static void JNICALL func2 (JNIEnv *env, jobject jobj)
{
printf("--- func2 called in version 2\n");
}
//定义批量注册的数组,是注册的关键部分
static const JNINativeMethod gMethods[] = {
{"func2", /* func2是在java中声明的native函数名 */
"()V", /* "()V"是函数的签名,可以通过javah获取。*/
(void*)func2
} ,
};
//这是JNI_OnLoad的声明,必须按照这样的方式声明
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void *reserved)
{
JNIEnv* env = NULL; //注册时在JNIEnv中实现的,所以必须首先获取它
jint result = -1;
//从JavaVM获取JNIEnv,一般使用1.4的版本
if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK)
return -1;
jclass clazz;
static const char* const kClassName="mj/jnitest/MyObject";
/*
* 这里可以找到要注册的类,前提是这个类已经加载到java虚拟机中。
* 这里说明,动态库和有native方法的类之间,没有任何对应关系。
*/
clazz = (*env)->FindClass(env, kClassName);
if(clazz == NULL) {
printf("cannot get class:%s\n", kClassName);
return -1;
}
/*
* 这里就是关键了,把本地函数和一个java类方法关联起来。
不管之前是否关联过,一律把之前的替换掉!
*/
if((*env)->RegisterNatives(env, clazz,gMethods, sizeof(gMethods)/sizeof(gMethods[0]))!= JNI_OK)
{
printf("register native method failed!\n");
return -1;
}
//这里很重要,必须返回版本,否则加载会失败。
return JNI_VERSION_1_4;
}
对他进行编译后,得到一个libjni2.so。
2.4 C++用法说明
上面的用法是c语言中的用法,在C++中更简单。
JavaVM和JNIEnv都是经过简单封装的类,可以直接按照如下方式调用:
(vm->GetEnv((void**)&env, JNI_VERSION_1_4)
env->FindClass(kClassName);
env->RegisterNatives(clazz,gMethods, sizeof(gMethods)/sizeof(gMethods[0]))
2.5 Dalvik中动态库的原理简要分析
之所以出现这种结果,和jni的机制有关的,通过对Android中的Dalvik的分析,可以印证。
System.loadL