JNI 基礎 - Android 共享記憶體的序列化過程
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);
}
相關文章
- Android匿名共享記憶體(Ashmem)原理Android記憶體
- Android NDK開發之JNI基礎Android
- JNI記憶體管理及優化記憶體優化
- Java記憶體模型的基礎Java記憶體模型
- 【Java基礎】實體記憶體&虛擬記憶體Java記憶體
- 記憶體訪問全過程記憶體
- java基礎-記憶體分配Java記憶體
- Golang 共享記憶體Golang記憶體
- POSIX 共享記憶體記憶體
- [Linux]共享記憶體Linux記憶體
- Linux共享記憶體的管理Linux記憶體
- Java 執行過程中的記憶體模型Java記憶體模型
- [Java基礎]記憶體洩漏和記憶體溢位Java記憶體溢位
- Java基礎知識_記憶體Java記憶體
- JavaAgent型記憶體馬基礎Java記憶體
- Qt共享記憶體QSharedMemoryQT記憶體
- Linux共享記憶體(二)Linux記憶體
- nginx共享記憶體分析Nginx記憶體
- QT之共享記憶體QT記憶體
- nginx中共享記憶體的使用Nginx記憶體
- 記一次"記憶體洩露"排查過程記憶體洩露
- OpenResty 和 Nginx 的共享記憶體區是如何消耗實體記憶體的RESTNginx記憶體
- 程式執行過程記憶體分析詳解記憶體
- 記一次使用windbg排查記憶體洩漏的過程記憶體
- 分析oc物件的記憶體結構及其建立過程物件記憶體
- Android記憶體管理Android記憶體
- 記錄一次記憶體洩漏排查過程記憶體
- Android 是如何管理 App 記憶體的 — Android 記憶體優化第二彈AndroidAPP記憶體優化
- 【重溫基礎】22.記憶體管理記憶體
- Java 併發基礎之記憶體模型Java記憶體模型
- 記一次 Java 應用記憶體洩漏的定位過程Java記憶體
- Android native程式間通訊例項-binder結合共享記憶體Android記憶體
- 【記憶體管理】Oracle如何使用ASMM自動共享記憶體管理記憶體OracleASM
- 記一次透過Memory Analyzer分析記憶體洩漏的解決過程記憶體
- 記一次堆外記憶體洩漏排查過程記憶體
- PostgreSQL共享記憶體裡的內容(initCommunication)SQL記憶體
- Android記憶體洩漏Android記憶體
- Android 記憶體抖動Android記憶體