前言
如果要对android系统有一个深入的理解,Native层C/C++是代码是必看的,Binder的底层实现,Input子系统,Looper采用都是JAVA和C++混合的方式设计的模块。要看懂这些Native的代码首先要了解的是JNI
JNI是什么
JNI是Java Native Interface的缩写,翻译就是JAVA本地接口,其实就是JAVA调用C/C++的一套接口
为什么使用JNI?
a.效率上C&C++比Java高,
b.C&C++的反编译比Java难度高
c.如果之前用C&C++开发的模块,可以通过JNI来复用
但是一旦使用JNI,就会让Java失去跨平台功能,需要在不同的系统平台下编译本地语言
JNI基本使用-静态注册
JNI基本使用-动态注册
动态注册对比静态注册
1.静态注册
编写不方便,JNI 方法名字必须遵循规则且名字很长
程序运行效率低,因为初次调用native函数时需要根据根据函数名在JNI层中搜索对应的本地函数,然后建立对应关系,这个过程比较耗时
2.动态注册
流程更加清晰可控
效率更高
JNI基本使用-将Native层的类和Java的类绑定
JNI基本使用-拿到JAVA层的保存的Native对象并调用Native层的方法
extern "C" JNIEXPORT jint JNICALL
Java_com_kobe_startjni_MainActivity_getValue(
JNIEnv *env,
jobject object) {
jclass jclazz = env->FindClass("com/kobe/startjni/MainActivity");
jfieldID jfield = env->GetFieldID(jclazz, "nativeMainActivity", "J");
//将Java层的nativeMainActivity的值强制转化成Native层的NativeMainActivity的指针
NativeMainActivity *mainActivity = (NativeMainActivity *) env->GetLongField(object, jfield);
return mainActivity->getValue();
}
JNI基本使用-Native层的对象调用Java层的对象的方法
extern "C" JNIEXPORT void JNICALL
Java_com_kobe_startjni_MainActivity_startCallBack(
JNIEnv *env,
jobject /* this */ object) {
jclass jclazz = env->FindClass("com/kobe/startjni/MainActivity");
jfieldID jfield = env->GetFieldID(jclazz, "nativeMainActivity", "J");
jmethodID jmethod = env->GetMethodID(jclazz, "callBack", "()V");
env->CallVoidMethod(mainActivity->mainActivity, jmethod);
}
JNI基本使用-在Native中创建Java对象
extern "C" JNIEXPORT void JNICALL
Java_com_kobe_startjni_MainActivity_createJavaObject(
JNIEnv *env,
jobject /* this */ object) {
jclass jclazz1 = env->FindClass("com/kobe/startjni/MainActivity");
jclass jclazz2 = env->FindClass("com/kobe/startjni/MyClass");
jfieldID jfield = env->GetFieldID(jclazz1, "myClass", "Ljava/lang/Object;");
//找到MyClass的构造函数
jmethodID init = env->GetMethodID(jclazz2, "<init>", "()V");
//在native层中创建java层的MyClass对象
jobject myclass = env->NewObject(jclazz2, init);
//将MyClass对象赋值到java层中MainActivity的属性myClass
env->SetObjectField(object, jfield, myclass);
}
总结
1.Java层调用Native层的方法,只能通过动态注册或者静态注册的JNI接口
2.Java层可以保存Native层对象的指针long,Native层可以保存Java层的对象jobject(NewGlobalRef),一定要注意内存泄露
3.Native层可以通过类似反射的方式,设置Java层对象的属性或者回调Java层对象的方法
4.Native层可以创建Java层的对象,但是Java层无法直接创建Native层的对象,需要通过JNI的接口。