Android Framework 소스의 JNI 메소드 등록 프로세스
/*
* Register android native functions with the VM.
*/
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
ATRACE_NAME("RegisterAndroidNatives");
/*
* This hook causes all future threads created in this process to be
* attached to the JavaVM. (This needs to go away in favor of JNI
* Attach calls.)
*/
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
ALOGV("--- registering native functions ---
");
/*
* Every "register" function calls one or more things that return
* a local reference (e.g. FindClass). Because we haven't really
* started the VM yet, they're all getting stored in the base frame
* and never released. Use Push/Pop to manage the storage.
*/
env->PushLocalFrame(200);
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
방법 중 먼저 라인 생성 방법을javaCreateThreadEtc로 설정한 다음register를 통해jni_procs에서 jni 방법을 등록했습니다.
register_jni_procs 함수 매개변수 RegJNIRec은 미리 정의된 매크로입니다.
#ifdef NDEBUG
#define REG_JNI(name) { name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
};
#else
#define REG_JNI(name) { name, #name }
struct RegJNIRec {
int (*mProc)(JNIEnv*);
const char* mName;
};
#endif
코드에서 볼 수 있듯이 RegJNIRec는 구조체로 mProc 수신 파라미터가 JNIEnv 포인터로 되돌아오는 값이 int인 함수 포인터를 포함하고 있다.
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
····
}
register_jni_procs 함수는 jni 메서드의 등록을 위해 RegJNIRec 배열에서 mProc 메서드를 반복적으로 호출합니다.
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
ALOGD("----------!!! %s failed to load
", array[i].mName);
#endif
return -1;
}
}
return 0;
}
여기는registerandroid_content_AssetManager 메서드의 등록은 등록 프로세스를 분석합니다.우선registerandroid_content_AssetManager 메서드의 설명은 다음과 같은 네임스페이스android 아래에 있습니다.
namespace android {
/*
* JNI-based registration functions. Note these are properly contained in
* namespace android.
*/
extern int register_android_app_admin_SecurityLog(JNIEnv* env);
extern int register_android_content_AssetManager(JNIEnv* env);
그에 상응하는 실현 조작은androidutil_AssetManager.cpp 파일
int register_android_content_AssetManager(JNIEnv* env)
{
......
return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
NELEM(gAssetManagerMethods));
}
gAssetManagerMethods는 현재 등록해야 하는 jni의 방법 목록입니다.
static const JNINativeMethod gAssetManagerMethods[] = {
/* name, signature, funcPtr */
// Basic asset stuff.
{ "openAsset", "(Ljava/lang/String;I)J",
(void*) android_content_AssetManager_openAsset },
{ "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
(void*) android_content_AssetManager_openAssetFd },
{ "openNonAssetNative", "(ILjava/lang/String;I)J",
(void*) android_content_AssetManager_openNonAssetNative },
{ "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
(void*) android_content_AssetManager_openNonAssetFdNative },
{ "list", "(Ljava/lang/String;)[Ljava/lang/String;",
(void*) android_content_AssetManager_list },
{ "destroyAsset", "(J)V",
(void*) android_content_AssetManager_destroyAsset },
{ "readAssetChar", "(J)I",
(void*) android_content_AssetManager_readAssetChar },
{ "readAsset", "(J[BII)I",
(void*) android_content_AssetManager_readAsset },
{ "seekAsset", "(JJI)J",
(void*) android_content_AssetManager_seekAsset },
{ "getAssetLength", "!(J)J",
(void*) android_content_AssetManager_getAssetLength },
{ "getAssetRemainingLength", "!(J)J",
(void*) android_content_AssetManager_getAssetRemainingLength },
{ "addAssetPathNative", "(Ljava/lang/String;Z)I",
(void*) android_content_AssetManager_addAssetPath },
{ "addOverlayPathNative", "(Ljava/lang/String;)I",
(void*) android_content_AssetManager_addOverlayPath },
{ "isUpToDate", "()Z",
(void*) android_content_AssetManager_isUpToDate },
// Resources.
{ "getLocales", "()[Ljava/lang/String;",
(void*) android_content_AssetManager_getLocales },
{ "getNonSystemLocales", "()[Ljava/lang/String;",
(void*) android_content_AssetManager_getNonSystemLocales },
{ "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
(void*) android_content_AssetManager_getSizeConfigurations },
{ "setConfiguration", "!(IILjava/lang/String;IIIIIIIIIIIIII)V",
(void*) android_content_AssetManager_setConfiguration },
{ "getResourceIdentifier","!(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
(void*) android_content_AssetManager_getResourceIdentifier },
{ "getResourceName","!(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getResourceName },
{ "getResourcePackageName","!(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getResourcePackageName },
{ "getResourceTypeName","!(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getResourceTypeName },
{ "getResourceEntryName","!(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getResourceEntryName },
{ "loadResourceValue","!(ISLandroid/util/TypedValue;Z)I",
(void*) android_content_AssetManager_loadResourceValue },
{ "loadResourceBagValue","!(IILandroid/util/TypedValue;Z)I",
(void*) android_content_AssetManager_loadResourceBagValue },
{ "getStringBlockCount","!()I",
(void*) android_content_AssetManager_getStringBlockCount },
{ "getNativeStringBlock","!(I)J",
(void*) android_content_AssetManager_getNativeStringBlock },
{ "getCookieName","(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getCookieName },
{ "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
(void*) android_content_AssetManager_getAssignedPackageIdentifiers },
// Themes.
{ "newTheme", "()J",
(void*) android_content_AssetManager_newTheme },
{ "deleteTheme", "(J)V",
(void*) android_content_AssetManager_deleteTheme },
{ "applyThemeStyle", "(JIZ)V",
(void*) android_content_AssetManager_applyThemeStyle },
{ "copyTheme", "(JJ)V",
(void*) android_content_AssetManager_copyTheme },
{ "clearTheme", "(J)V",
(void*) android_content_AssetManager_clearTheme },
{ "loadThemeAttributeValue", "!(JILandroid/util/TypedValue;Z)I",
(void*) android_content_AssetManager_loadThemeAttributeValue },
{ "getThemeChangingConfigurations", "!(J)I",
(void*) android_content_AssetManager_getThemeChangingConfigurations },
{ "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
(void*) android_content_AssetManager_dumpTheme },
{ "applyStyle","!(JIIJ[I[I[I)Z",
(void*) android_content_AssetManager_applyStyle },
{ "resolveAttrs","!(JII[I[I[I[I)Z",
(void*) android_content_AssetManager_resolveAttrs },
{ "retrieveAttributes","!(J[I[I[I)Z",
(void*) android_content_AssetManager_retrieveAttributes },
{ "getArraySize","!(I)I",
(void*) android_content_AssetManager_getArraySize },
{ "retrieveArray","!(I[I)I",
(void*) android_content_AssetManager_retrieveArray },
// XML files.
{ "openXmlAssetNative", "(ILjava/lang/String;)J",
(void*) android_content_AssetManager_openXmlAssetNative },
// Arrays.
{ "getArrayStringResource","(I)[Ljava/lang/String;",
(void*) android_content_AssetManager_getArrayStringResource },
{ "getArrayStringInfo","!(I)[I",
(void*) android_content_AssetManager_getArrayStringInfo },
{ "getArrayIntResource","!(I)[I",
(void*) android_content_AssetManager_getArrayIntResource },
{ "getStyleAttributes","!(I)[I",
(void*) android_content_AssetManager_getStyleAttributes },
// Bookkeeping.
{ "init", "(Z)V",
(void*) android_content_AssetManager_init },
{ "destroy", "()V",
(void*) android_content_AssetManager_destroy },
{ "getGlobalAssetCount", "()I",
(void*) android_content_AssetManager_getGlobalAssetCount },
{ "getAssetAllocations", "()Ljava/lang/String;",
(void*) android_content_AssetManager_getAssetAllocations },
{ "getGlobalAssetManagerCount", "()I",
(void*) android_content_AssetManager_getGlobalAssetManagerCount },
};
여기서 Andoird에서는 서로 다른 기존 JNI 방식을 사용하여 native의 함수를 정의합니다.여기서 중요한 차이점은 Andorid가 자바와 C 함수의 매핑 테이블 배열을 사용하고 함수의 매개 변수와 반환 값을 설명하는 것이다.이 배열의 유형은 JNINativeMethod이고 jni에 정의되어 있습니다.h의 헤더 파일은 다음과 같습니다.
typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
첫 번째 변수 name은 Java의 함수 이름입니다.두 번째 변수signature, 함수의 매개 변수와 반환 값을 문자열로 설명하는 세 번째 변수 fnPtr는 함수 바늘로 C 함수를 가리킨다.그 중에서 이해하기 어려운 것은 두 번째 매개 변수이다. 예를 들어'()V'(II)V'(Ljava/lang/string, Ljava/lang/string,)V "실제로 이 문자들은 함수의 매개 변수 유형과 일일이 대응한다."() "의 문자는 매개 변수를 나타내고, 뒤에 있는 문자는 되돌아오는 값을 나타냅니다. 예를 들어"() V "는void Func () 를 나타냅니다.(II) V "void Func(int, int)를 나타냅니다. 구체적인 각 문자의 대응 관계는 다음과 같습니다. Java 유형 C 유형 V void Z jboolean boolean I jint Jjlong 롱 D jdouble double F jfloat float B jbyte byte C jchar S jshort 배열은"["[I jint Array int [] [F jfloat Array float By] [jby Array Arteby] [] [jby][C jcharararray char[][S jshort Array short[] [D jdouble Array double[][J jlong Array long[] [Z jboolean Array boolean[] 위에 있는 것은 모두 기본 유형입니다.Java 함수의 매개 변수가 class이면 "L"로 시작하고 ";"끝 중간에 "/"로 구분된 가방과 클래스 이름입니다.그에 대응하는 C함수 이름의 매개 변수는jobject이다.하나의 예외는String클래스인데 그에 대응하는 클래스는 jstring Ljava/lang/String이다.String jstring Ljava/net/Socket; Socket jobject JAVA 함수가 포함된 클래스에 있으면 $를 클래스 이름 사이의 구분자로 사용합니다.
RegisterMethodsOrDie 메서드의 구현:
static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className,
const JNINativeMethod* gMethods, int numMethods) {
int res = AndroidRuntime::registerNativeMethods(env, className, gMethods, numMethods);
LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
return res;
}
최종적으로 모든 jni의native를 등록하는 것을 알 수 있다.이로써 Android Framework의 JNI 등록 메소드 프로세스가 완전히 완료되었습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.