代码请看:NDKPractice项目的jni09
1. 面试题:
- 进程间的通信方式有哪些
- binder 和 socket 通信的区别有哪些
- 从传输性能上说 :
Socket
,传输效率低
,开销大
,主要用在跨网络的进程间通信
;消息队列和管道采用存储-转发方式.数据先从发送方拷贝到内存开辟的缓存区中,
然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程。Binder
只需要拷贝一次(因为内存映射) - 从安全性上来说: Socket 没有任何安全措施,完全依赖上层协议来确保。
Binder
通过包名和类名在serviceManager
中进行查找,Binder.getCallingUID();
就能取得对方UID来检验它的身分等。还可以进行checkCallingPermission()
等 - 总结:(binder 共享内存,Soket需要copy内存) Socket 远程,本地低速(zygote)
- 从传输性能上说 :
- Android 为什么在大部分场景下用 Binder 进行进程间通信 (效率高,开销小,安全性高)
- Serializable 和 Parcelable 之间的区别
Serializable :主要是IO操作,消耗较大 ,好处就是简单
。存储设置中或将对象序列化后通过网络传输时使用
Parcelable :因为原理是共享内存
,所以效率高,内存消耗小。应用程序在内存间数据传输时推荐使用 - Parcelable 序列化和反序列化的具体过程
2. 重点: Native 构建对象如何与 Java 层对应
2.1 opencv Mat 源码阅读
Java -> Mat.java = C++ Mat.cpp 对象
1 | public class Mat {// Java 对象 |
c 层 构建的对象
1 | JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__DDI |
2.2 Parcel.java 的源码
java层 创建对象调用 c 层的创建对象并获取到 c 层的指针(地址):
1 | private void init(long nativePtr) { |
c 层创建 Parcel 对象
1 | static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz) |
java 层调用 c 层写入Int
1 | // nativePtr 指针地址 |
c 层的写入:
- mData : 共享内存的首地址
- mDataPos:内存首地址的当前逻动位置
- mDataCapacity:共享内存的总大小
1 | template<class T> |
3.手写个Native层的Parcel.cpp,便于理解
1 |
|
java 层调用:
1 | var parcel = Parcel() |