前面看到使用static natvie方法,它有如下几个弊端:
需要为每个static natvie方法的java类使用javah生成一个头文件
javah生成的头文件名太长
初次使用native函数时需寻找JNI层函数来建立关联,影响性能
动态注册
动态注册的过程主要是在System.loadLibrary()时会调用JNI_OnLoad()函数,在里面我们调用Env->RegisterNatives来实行注册。
例如如下的例子:
创建一个native类
新建一个Android空白工程,在MainActivity.java中的onCreate 中添加:
NativeClass testClass = new NativeClass();
setTitle("Native Class"+testClass.getStr()+String.valueOf(testClass.getAdd(1, 5)));
NativeClass.java :
package com.example.testdr;
public class NativeClass {
static {
System.loadLibrary("cpplib");
}
public int getAdd(int a, int b) {
return nativeGetAdd(a, b);
}
public String getStr() {
return "Title:";
}
private native int nativeGetAdd(int a, int b);
}
创建c++ native实现
创建Android.mk文件(略)
main.c
#include <jni.h>
#include <assert.h>
#include <stdio.h>
jint getAdd(JNIEnv* env, jobject obj, jint a, jint b)
{
return (a + b);
}
static JNINativeMethod g_NativeMethods[] = {
{"nativeGetAdd", "(II)I", (void*)getAdd},
};
static const char* classPathName = "com/example/testdr/NativeClass";
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv *env = NULL;
if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) {
return JNI_ERR;
}
jclass clazz = (*env)->FindClass(env, classPathName);
if (clazz == NULL) {
return JNI_ERR;
}
assert(env != NULL);
if ((*env)->RegisterNatives(env, clazz, g_NativeMethods, 1) < 0) {
return JNI_ERR;
}
return JNI_VERSION_1_4;
}
这里注意c和c++的不同,如果用c++,以上如下:
vm->GetEnv((void**)&env, JNI_VERSION_1_4)
jclass clazz = env->FindClass(classPathName);
env->RegisterNatives(clazz, g_NativeMethods, 1)