日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android系统的JNI原理分析(二)- 数据类型转换和方法签名

發布時間:2024/1/1 Android 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android系统的JNI原理分析(二)- 数据类型转换和方法签名 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

聲明

  • 前階段在項目中使用了Android的JNI技術,在此文中做些技術知識總結。
  • 本文參考了一些書籍的若干章節,比如《Android進階解密-第9章-JNI原理》、《深入理解Android虛擬機-第4章-分析JNI》、《深入理解Android系統-第2章-分析JNI》、《Android NDK Beginner_'s Guide》等
  • 本文使用的代碼時LineageOS的cm-14.1,對應Android 7.1.2,可以參考我的另一篇博客:cm-14.1 Android系統啟動過程分析(〇)-如何下載Nexus5的LineageOS14.1(cm-14.1)系統源碼并編譯、刷機

1 Java層和JNI層的數據類型轉換

????進入到源碼路徑:
vim ~/LineageOS/frameworks/base/media/jni/android_
media_MediaRecorder.cpp,查看函數android_media_MediaRecorder_native_setup:

static void android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,jstring packageName, jstring opPackageName) {ALOGV("setup");ScopedUtfChars opPackageNameStr(env, opPackageName);sp<MediaRecorder> mr = new MediaRecorder(String16(opPackageNameStr.c_str()));if (mr == NULL) {jniThrowException(env, "java/lang/RuntimeException", "Out of memory");return;}if (mr->initCheck() != NO_ERROR) {jniThrowException(env, "java/lang/RuntimeException", "Unable to initialize media recorder");return;}// create new listener and give it to MediaRecordersp<JNIMediaRecorderListener> listener = new JNIMediaRecorderListener(env, thiz, weak_this);mr->setListener(listener);// Convert client name jstring to String16const char16_t *rawClientName = reinterpret_cast<const char16_t*>(env->GetStringChars(packageName, NULL));jsize rawClientNameLen = env->GetStringLength(packageName);String16 clientName(rawClientName, rawClientNameLen);env->ReleaseStringChars(packageName,reinterpret_cast<const jchar*>(rawClientName));// pass client package name for permissions trackingmr->setClientName(clientName);setMediaRecorder(env, thiz, mr); }

????其中jobject、jstring類型參數都是JNI層的數據類型,Java層數據類型到JNI層就要轉換為JNI層數據結構。包括基本數據類型引用數據類型

1.1 Java層至JNI層基本數據類型的轉換

Java類型JNI類型C++類型關系描述簽名占內存大小
booleanjbooleanunsigned char 或 unit8_t布爾類型Z1
intjintint或long整形I4
floatjfloatfloat單精度類型F4
doublejdoubledouble雙精度類型D8
longjlonglong長整形J8
shortjshortshort短整型S2
charjcharunsigned short字符C2
bytejbytesigned char字節類型B1
voidvoidvoid空類型V

????從轉換表中可以看出Java層基本數據類型轉換到JNI層只需將數據類型前加個“j”即可(除了void類型)。

1.2 Java層至JNI層引用數據類型的轉換

JavaNative簽名(以;結尾)
所有對象jobjectL+classname +;
ClassjclassLjava/lang/Clas;
StringjstringLjava/lang/String;
TrowablejthrowableLjava/lang/Throwable;
Object[]jobjectArray[L+classname +;
byte[]jbyteArray[B
char[]jcharArray[C
double[]jdoubleArray[D
float[]jfloatArray[F
int[]jintArray[I
short[]jshortArray[S
long[]jlongArray[J
boolean[]jbooleanArray[Z

????以~/LineageOS/frameworks/base/media/java/android/media/
MediaRecorder.java中的native_setup方法為例:

private native final void native_setup(Object mediarecorder_this,String clientName, String opPackageName) throws IllegalStateException;

????對應在~/LineageOS/frameworks/base/media/jni/android_
media_MediaRecorder.cpp,查看函數android_media_MediaRecorder_native_setup:

static void android_media_MediaRecorder_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,jstring packageName, jstring opPackageName) { ...省略n行... }

????可以發現:Object類型轉換為jobject類型,String類型轉換為jstring類型。

2 方法簽名

????進入到源碼路徑: vim ~/LineageOS/frameworks/base/media/jni/
android_media_MediaRecorder.cpp,在數組gMethods[]中可看到簽名信息:

static const JNINativeMethod gMethods[] = {{"setCamera", "(Landroid/hardware/Camera;)V", (void *)android_media_MediaRecorder_setCamera},{"setVideoSource", "(I)V", (void *)android_media_MediaRecorder_setVideoSource},{"setAudioSource", "(I)V", (void *)android_media_MediaRecorder_setAudioSource},{"setOutputFormat", "(I)V", (void *)android_media_MediaRecorder_setOutputFormat},{"setVideoEncoder", "(I)V", (void *)android_media_MediaRecorder_setVideoEncoder},{"setAudioEncoder", "(I)V", (void *)android_media_MediaRecorder_setAudioEncoder},{"setParameter", "(Ljava/lang/String;)V", (void *)android_media_MediaRecorder_setParameter},{"_setOutputFile", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaRecorder_setOutputFileFD},{"setVideoSize", "(II)V", (void *)android_media_MediaRecorder_setVideoSize},{"setVideoFrameRate", "(I)V", (void *)android_media_MediaRecorder_setVideoFrameRate},{"setMaxDuration", "(I)V", (void *)android_media_MediaRecorder_setMaxDuration},{"setMaxFileSize", "(J)V", (void *)android_media_MediaRecorder_setMaxFileSize},{"_prepare", "()V", (void *)android_media_MediaRecorder_prepare},{"getSurface", "()Landroid/view/Surface;", (void *)android_media_MediaRecorder_getSurface},{"getMaxAmplitude", "()I", (void *)android_media_MediaRecorder_native_getMaxAmplitude},{"start", "()V", (void *)android_media_MediaRecorder_start},{"stop", "()V", (void *)android_media_MediaRecorder_stop},{"pause", "()V", (void *)android_media_MediaRecorder_pause},{"resume", "()V", (void *)android_media_MediaRecorder_resume},{"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset},{"release", "()V", (void *)android_media_MediaRecorder_release},{"native_init", "()V", (void *)android_media_MediaRecorder_native_init},{"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V",(void *)android_media_MediaRecorder_native_setup},{"native_finalize", "()V", (void *)android_media_MediaRecorder_native_finalize},{"native_setInputSurface", "(Landroid/view/Surface;)V", (void *)android_media_MediaRecorder_setInputSurface }, };

????簡單地說,存在簽名的原因就是Java語言的方法是可以重載的,重載的方法名字相同而參數不同,所以JNI僅通過方法名無法確定對應的是重載的哪個方法,必須要參數簽名來輔助其關聯。

避免博客拖太長,后續參見下篇Android系統的JNI原理分析(三)- JNIEnv

總結

以上是生活随笔為你收集整理的Android系统的JNI原理分析(二)- 数据类型转换和方法签名的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。