Parcel源码分析
parcel的简单使用
Parcel parcel=Parcel.obtain();
parcel.writeInt(12);
parcel.writeInt(24);
parcel.setDataPosition(0);
int number1 = parcel.readInt();
int number2 = parcel.readInt();
Log.e(TAG, "number1: "+number1+",number2:"+number2 );
Parcel.obtain()源码分析
public static Parcel obtain() {
//从缓冲池中取,没有就直接new
final Parcel[] pool = sOwnedPool;
synchronized (pool) {
Parcel p;
for (int i=0; i<POOL_SIZE; i++) {
p = pool[i];
if (p != null) {
pool[i] = null;
if (DEBUG_RECYCLE) {
p.mStack = new RuntimeException();
}
p.mReadWriteHelper = ReadWriteHelper.DEFAULT;
return p;
}
}
}
return new Parcel(0);
}
最终会走到
private void init(long nativePtr) {
if (nativePtr != 0) {
mNativePtr = nativePtr;
mOwnsNativeParcelObject = false;
} else {
mNativePtr = nativeCreate();
mOwnsNativeParcelObject = true;
}
}
nativeCreate源码分析
private static native long nativeCreate();
这时候我们去下载好的ndk源码.,找到,比如我的是放在D盘
D:\ndk\android-6.0.1_r1\android-6.0.1_r1\frameworks\base\core\jni下面的android_os_Parcel.cpp
{"nativeCreate", "()J", (void*)android_os_Parcel_create},
找到android_os_Parcel_create
static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
{
//实际就是new个Parcel对象,并转换对象为long类型
Parcel* parcel = new Parcel();
return reinterpret_cast<jlong>(parcel);
}
parcel.writeInt()源码分析
private static native void nativeWriteInt(long nativePtr, int val);
继续看android_os_Parcel.cpp源码对nativeWriteInt分析
{"nativeWriteInt", "(JI)V", (void*)android_os_Parcel_writeInt},
static void android_os_Parcel_writeInt(JNIEnv* env, jclass clazz, jlong nativePtr, jint val) {
//long转换成Parcel对象
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeInt32(val);
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
writeInt32这个源码需要到D:\ndk\android-6.0.1_r1\android-6.0.1_r1\frameworks\native\libs\binder下面的Parcel.cpp
status_t Parcel::writeInt32(int32_t val)
{
return writeAligned(val);
}
template<class T>//相当于java中的泛型
status_t Parcel::writeAligned(T val) {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
if ((mDataPos+sizeof(val)) <= mDataCapacity) {
restart_write:
*reinterpret_cast<T*>(mData+mDataPos) = val;//mData代表首地址,mDataPos代表指针偏移量
return finishWrite(sizeof(val));
}
status_t err = growData(sizeof(val));
if (err == NO_ERROR) goto restart_write;
return err;
}
finishWrite源码分析
status_t Parcel::finishWrite(size_t len)
{
if (len > INT32_MAX) {
// don't accept size_t values which may have come from an
// inadvertent conversion from a negative int.
return BAD_VALUE;
}
//printf("Finish write of %d\n", len);
mDataPos += len;//指针向后+偏移量
ALOGV("finishWrite Setting data pos of %p to %zu", this, mDataPos);
if (mDataPos > mDataSize) {
mDataSize = mDataPos;
ALOGV("finishWrite Setting data size of %p to %zu", this, mDataSize);
}
//printf("New pos=%d, size=%d\n", mDataPos, mDataSize);
return NO_ERROR;
}
parcel.readInt()源码分析
private static native int nativeReadInt(long nativePtr);
{"nativeReadInt", "(J)I", (void*)android_os_Parcel_readInt},
static jint android_os_Parcel_readInt(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
return parcel->readInt32();
}
return 0;
}
最终会走到
template<class T>
status_t Parcel::readAligned(T *pArg) const {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
if ((mDataPos+sizeof(T)) <= mDataSize) {
const void* data = mData+mDataPos;
//指针向后移动
mDataPos += sizeof(T);
//取值
*pArg = *reinterpret_cast<const T*>(data);
return NO_ERROR;
} else {
return NOT_ENOUGH_DATA;
}
}
android自己动手实现内存共享
首先还是使用
Parcel parcel=new Parcel();
parcel.writeInt(12);
parcel.writeInt(24);
parcel.setDataPosition(0);
int number1 = parcel.readInt();
int number2 = parcel.readInt();
Log.e(TAG, "number1: "+number1+",number2:"+number2 );
Parcel类的创建
public class Parcel {
private static long mNativePtr;
static {
System.loadLibrary("native-lib");
mNativePtr = nativeCreate();
}
public void writeInt(int value) {
nativeWriteInt(mNativePtr, value);
}
public void setDataPosition(int pos) {
nativeSetDataPosition(mNativePtr, pos);
}
public final int readInt() {
return nativeReadInt(mNativePtr);
}
//c层构建一个Parcel.cpp对象,然后指针地址
private static native long nativeCreate();
//写int
private static native void nativeWriteInt(long mNativePtr, int value);
//读int
private static native int nativeReadInt(long nativePtr);
//写完之后重新设置偏移位置
private static native void nativeSetDataPosition(long nativePtr, int pos);
}
生成头文件,这里我就不阐述了,之前写过了。生成头文件后,我们就可以写c代码了
#include <string>
#include <malloc.h>
#include <android/log.h>
#define TAG "JNI_TAG"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
#include "com_peakmain_ndk_Parcel.h"
extern "C"
//c/c++ 更加灵活,更加接近底层,操作的是一块内存
class Parcel {
char *mData;//char共享内存的首地址
int mDataPos = 0;//=0,默认没有赋值的话
public:
Parcel() {
mData = (char *) (malloc(1024));
}
void writeInt(jint value) {
//赋值
*reinterpret_cast<int *>(mData + mDataPos) = value;
mDataPos += sizeof(int);
}
//设置当前指针的位置
void setDataPosition(jint position) {
mDataPos = position;
}
jint readInt() {
int result = *reinterpret_cast<int*>(mData+mDataPos);//取当前地址的值
mDataPos += sizeof(int);//指针偏移4
return result;
}
};
JNIEXPORT jlong JNICALL Java_com_peakmain_ndk_Parcel_nativeCreate
(JNIEnv *env, jclass jclzz) {
Parcel *parcel = new Parcel();
return reinterpret_cast<jlong>(parcel);
}
JNIEXPORT void JNICALL Java_com_peakmain_ndk_Parcel_nativeWriteInt
(JNIEnv *env, jclass clazz, jlong nativePtr, jint value) {
Parcel *parcel = reinterpret_cast<Parcel *>(nativePtr);
parcel->writeInt(value);
}
JNIEXPORT jint JNICALL Java_com_peakmain_ndk_Parcel_nativeReadInt
(JNIEnv *env, jclass clazz, jlong nativePtr) {
Parcel *parcel = reinterpret_cast<Parcel *>(nativePtr);
return parcel->readInt();
}
JNIEXPORT void JNICALL Java_com_peakmain_ndk_Parcel_nativeSetDataPosition
(JNIEnv *env, jclass jclazz, jlong nativePtr, jint value) {
Parcel *parcel = (Parcel *) (nativePtr);
parcel->setDataPosition(value);
}
网友评论