【Android-系統】JNIEnv定義在哪

libnativehelper/include_jni/jni.h中

JNIEnv是什麼?

#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif
  • 如果用C++編譯器,那麼JNIEnv就是_JNIEnv
  • 如果用C編譯器,那麼JNIEnv就是JNIInvokeInterface

_JNIEnv是什麼呢?

請看:

struct _JNIEnv {
    const struct JNINativeInterface* functions;
#if defined(__cplusplus)
    jint GetVersion()
    { return functions->GetVersion(this); }
    jclass DefineClass(const char *name, jobject loader, const jbyte* buf, jsize bufLen)
    { return functions->DefineClass(this, name, loader, buf, bufLen); }
    
    ...
#endif
}
  • _JNIEnv是一個結構體
  • 它有一個JNINativeInterface成員
  • _JNIEnv所有的接口調用實際上都是轉手交給了JNINativeInterface

由此可見,無論是C還是C++,JNIEnv本質上都是JNINativeInterface

JNINativeInterface是什麼?

答:接口函數指針表

/*
 * Table of interface function pointers.
 */
struct JNINativeInterface {
    //預留了四個指針
    void*       reserved0;  
    void*       reserved1;
    void*       reserved2;
    void*       reserved3;
    
    //接口函數指針:
    jint        (*GetVersion)(JNIEnv *);

    jclass      (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, jsize);
    
    jclass      (*FindClass)(JNIEnv*, const char*);

    jmethodID   (*FromReflectedMethod)(JNIEnv*, jobject);
    jfieldID    (*FromReflectedField)(JNIEnv*, jobject);

	...(省略300多行)
  • 大約230個函數指針(Android8.1)

JNIEnv是在哪裏創建的?

從Zygote的啓動入口函數開始:

//frameworks\base\cmds\app_process\app_main.cpp
int main(int argc, char* const argv[]){
	...
	runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}

//
void AndroidRuntime::start(const char* className,...){
	...
	//初始化jni_invocation,實際上是導入libart.so庫,
	//然後找到創建虛擬機的函數並把地賦給JNI_CreateJavaVM_
	//後面將調用這個函數
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //啓動虛擬機:其實是調用JNI_CreateJavaVM_
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);
}

//libnativehelper\JniInvocation.cpp
bool JniInvocation::Init(const char* library) {
  ...
  if (handle_ == NULL) {
    //導入libart.so
    library = kLibraryFallback; 
    handle_ = dlopen(library, kDlopenFlags);
    ...
  }
  //找到JNI_CreateJavaVM函數,把其地址JNI_CreateJavaVM_
  if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_), "JNI_CreateJavaVM")) {
    return false;
  }
  ...
  return true;
}

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
    ...
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
    }
}

extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);
}

jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
  //調用前面從libart.so中找到的創建虛擬機的函數
  return JNI_CreateJavaVM_(p_vm, p_env, vm_args);
}

  • JNIEnv是在Zygote初始化的時候調用libart.so中的"JNI_CreateJavaVM"方法創建的
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章