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"方法創建的