前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React Native for Android源码分析 一《JNI智能指针之介绍篇》

React Native for Android源码分析 一《JNI智能指针之介绍篇》

作者头像
开发者技术前线
发布2020-11-23 11:20:58
1.3K0
发布2020-11-23 11:20:58
举报
文章被收录于专栏:开发者技术前线

React Native Android源码分析

为了提高文章质量,本人决定周三22.30(周六早10.30)定时推送技术相关文章,对于方案相关的文章将不在其他渠道发出,只在公众号首发,喜欢的朋友一定要记得哦!

导读


React Native 发布以来将近一年多了,也被抄的火爆到不行,包括RN的中文网和各种资料也很多,加之SE5,SE6语法升级,学习成本并不在于RN环境搭建和入门,关键还是对JS的入门掌握,无论你是用Native移动开发,H5前端开发,还是React Native的开发,都应该明白上层语言和底层交互,都离不开C, 今天就介绍下native中Jni过程中的指针运用。文章适合已经入门了RN的朋友看,推荐入门资料:Android 开发者转 React Native 必看教程汇总

JNI指针


通常的app中, JNI提供的native函数主要充当Java类的扩展,逻辑层在Java端,JNI端较少使用OOP的设计思想。 而对于native端功能较重的模块,例如开源的阅读器FBReader,native端与Java端有较多交互,即native会主动创建Java对象并调用它们的方法以实现功能,这时就需要考虑将native至Java的操作与访问框架化,形成更高层次的封装,以避免直接使用原始的JNI反射API集去操作Java对象。 对于ReactNative For Android而言,这套访问框架尤其重要,其核心就是JNI智能指针这个基本数据类型。它的实现基于C11标准,将先用几篇对这套native至Java的操作框架进行介绍,为后续分析打下良好基础。

JNI指针


通常的app中, JNI提供的native函数主要充当Java类的扩展,逻辑层在Java端,JNI端较少使用OOP的设计思想。 而对于native端功能较重的模块,例如开源的阅读器FBReader,native端与Java端有较多交互,即native会主动创建Java对象并调用它们的方法以实现功能,这时就需要考虑将native至Java的操作与访问框架化,形成更高层次的封装,以避免直接使用原始的JNI反射API集去操作Java对象。 对于ReactNative For Android而言,这套访问框架尤其重要,其核心就是JNI智能指针这个基本数据类型。它的实现基于C11标准,将先用几篇对这套native至Java的操作框架进行介绍,为后续分析打下良好基础。

Native引用


首先回顾一下Java Object(jobject)在native端的三种引用类型:

全局引用

类似于C语言中的全局变量。使用NewGlobalRef创建,支持跨线程访问 ,在调用释放DeleteGlobalRef销毁前,GC无法回收该引用对应的java object。

局部引用

概念上与C语言中的局部变量有相似点,但不等同。使用NewLocalRef创建, 只能在本线程内安全访问,当创建该引用的native调用链返回至JVM时,未销毁的局部引用会被JVM自动GC回收。但由于局部引用表容量有限,在返回至JVM前,可以调用DeleteLocalRef先行销毁,避免局部引用表超限引起崩溃。

弱全局引用

与全局引用一样具有全局作用域,但不会影响GC回收, GC可以随时回收该引用对应的java object。使用NewWeakGlobalRef创建,当需要使用时,需要将其升级为全局引用或者局部引用,若已被回收,会返回null,使用DeleteWeakGlobalRef销毁。该引用类型使用场景较少。

由上可见,JNI智能指针的第一个需求,就是要自动管理jobject的生命周期,当进入与离开对应作用域时,需要自动调用对应生命周期的创建与销毁函数。这在C++中,通常会结合构造与析构函数来进行配对调用。若功能仅限于此,就与普通的智能指针和mutext锁管理机制类似了,更重要的需求是在C++层提供与被管理的Java对象镜像结构的C++对象,形成高层次封装。这样,对jobject的访问与操作就会被封装在对应的镜像C++对象中,相关JNI反射调用的细节被隐藏,对于其他native模块而言,与Java层的交互被转化成了与这些镜像C++对象的交互,整个实现风格OOP化了。这些镜像C++对象被称为wrapper对象,其定义代码位于ReactAndroid/src/main/jni/first-party/fb/include/fb/fbjni/CoreClasses.h文件中。

先看一个使用范例:

代码语言:javascript
复制
 struct MyClass : public JavaClass<MyClass> {   constexpr static auto kJavaDescriptor = "Lcom/example/package/MyClass;";   void foo() { static auto method = javaClassStatic()->getMethod<void()>("foo");
method(self());
  }   static local_ref<javaobject> create(int i) { return newInstance(i);
  }
};auto obj = MyClass::create(10);
obj->foo();

Native的需求是在native端创建com.example.package.MyClass这个自定义的Java类的对象,并访问它的foo方法。

实现步骤


例子中实现的步骤是:

定义java的MyClass的wrapper C++类MyClass,所有wrapper均需要继承于JavaClass的一个模板实例,并将自身类型做为JavaClass的第一个模板类型参数,以供JavaClass获取具体wrapper的类型。

给static成员变量kJavaDescriptor赋值为对应Java类的全类名。 在wrapper类实现镜像方法foo(), 其会获取jclass的包装类JClass对象,并获取jmethod的包装类JMethod进行调用。

create工厂方法中使用newInstance构建镜像对象的实例,并将其存至局部智能指针local_ref<javaobject>。这样就可以通过智能指针访问wrapper class提供的foo方法,实现了native至Java的镜像映射。

除了实现对一个java类的的映射,还需要支持对java继承关系的映射。若java的MyClass有一子类MyChildClass,native层为其建立的wrapper class可如下:

代码语言:javascript
复制
struct MyChildClass : public JavaClass<MyChildClass, MyClass> {constexpr static auto kJavaDescriptor = "Lcom/example/package/MyChildClass;";
};

这里需要用到JavaClass的第二个模板参数,设为MyClass,它是JavaClass<MyChildClass, MyClass>这个模板实例的父类型。通过构造这样的继承链,MyChildClass获得了父类MyClass提供的java方法映射,完成了继承关系在native层的映射。 上面例子中,返回的obj可以调用wrapper提供的镜像方法,应可以看出,智能指针存放的并不是原始的jobject,而是更抽象的wrapper MyClass对象。与通常的智能指针不一样,local_ref局部指针的模板参数并不直接指代其存储值的类型。在上面代码中,obj的类型除了根据create函数签名推导出的local_ref<MyClass::javaobject>,也可以写成local_ref<MyClass>,这两者是等价的。若native端只需要保存jobject,不需直接调用wrapper类的方法,也可以使用local_ref<jobject>。

疑问


这就带来几个问题:

javaObject与jobject的关系是什么?

为什么智能指针的模板参数能够接受多种类型?

模板参数起到的作用是什么?

结尾


这些问题将在下一篇智能指针的具体实现篇中解答。 综上介绍,在ReactNative for Android中,为了简化Native层对Java层的调用,提供了镜像结构的wrapper class,结合智能指针,将jobject的生命周期管理、java method的反射调用等“样板”代码封装起来,是比较优雅的JNI调用框架。

RN资料传送门:http://www.open-open.com/news/view/937e77

作者系曾360,百度,平安高级架构师,首次发文,干货后续持续放送,欢迎关注!由于不是本人写的,本次是首次开启打赏,期待大神的下篇力作 !

Tamic开发社区

To You,For Me

Android & iOS

长按二维码关注

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开发者技术前线 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • React Native Android源码分析
  • 导读
  • JNI指针
  • JNI指针
  • Native引用
  • 实现步骤
  • 疑问
  • 结尾
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档