Android虚拟机art流程:JavaVM 和 JNIEnv 的初始化(3)

  • A+
所属分类:art虚拟机
JNIEnv* env;
  JavaVM* mJavaVM;
if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }

 

首先我们得要先看下 这两个结构体。

typedef _JavaVM JavaVM;
struct _JavaVM {
    const struct JNIInvokeInterface* functions;

#if defined(__cplusplus)
    jint DestroyJavaVM()
    { return functions->DestroyJavaVM(this); }
    jint AttachCurrentThread(JNIEnv** p_env, void* thr_args)
    { return functions->AttachCurrentThread(this, p_env, thr_args); }
    jint DetachCurrentThread()
    { return functions->DetachCurrentThread(this); }
    jint GetEnv(void** env, jint version)
    { return functions->GetEnv(this, env, version); }
    jint AttachCurrentThreadAsDaemon(JNIEnv** p_env, void* thr_args)
    { return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args); }
#endif /*__cplusplus*/
};

 

其实是接,主要是看下这个functions怎么去赋值,然后上层就可以用了。

typedef _JNIEnv JNIEnv;
struct _JNIEnv {
    /* do not rename this; it does not seem to be entirely opaque */
    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); }

    jclass FindClass(const char* name)
    { return functions->FindClass(this, name); }
...
}

也是一样的。接下看下怎么初始化这两个东东。

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

    return 0;
}

这个函数最终会到art里面,刚才在so赋值的, /art/art/runtime/java_vm_ext.cc

extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
....
 if (!Runtime::Create(options, ignore_unrecognized)) {
    return JNI_ERR;
  }
  Runtime* runtime = Runtime::Current();
  bool started = runtime->Start();
....
  *p_env = Thread::Current()->GetJniEnv();
  *p_vm = runtime->GetJavaVM();
  return JNI_OK;
}

建立一个Runtime 然后start,然后我们需要关注的两个指针最后都给赋值了。

bool Runtime::Create(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
  RuntimeArgumentMap runtime_options;
  return ParseOptions(raw_options, ignore_unrecognized, &runtime_options) &&
      Create(std::move(runtime_options));
}
bool Runtime::Create(RuntimeArgumentMap&& runtime_options) {
....
  instance_ = new Runtime;
  if (!instance_->Init(std::move(runtime_options))) {
    instance_ = nullptr;
    return false;
  }
  return true;
}

这边的create 很正常 单例指针什么的,然后init函数。

bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
  RuntimeArgumentMap runtime_options(std::move(runtime_options_in));
  ScopedTrace trace(__FUNCTION__);
  CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);

  MemMap::Init();

 ...

  oat_file_manager_ = new OatFileManager;

 ...
  boot_class_path_string_ = runtime_options.ReleaseOrDefault(Opt::BootClassPath);
 ...
  heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),
      ...
      runtime_options.GetOrDefault(Opt::EnableHSpaceCompactForOOM),
           runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs));

  ...

  java_vm_ = new JavaVMExt(this, runtime_options);
    Thread::Startup();


  Thread* self = Thread::Attach("main", false, nullptr, false);
  ...
  class_linker_ = new ClassLinker(intern_table_);
  ...
      OpenDexFiles(dex_filenames,
                   dex_locations,
                   runtime_options.GetOrDefault(Opt::Image),
                   &boot_class_path);
   ...

这里的内容好多的。包括Heap的家里 ClassLinker的建立等等,这个等到下一节再讲吧。 我们关注的java_vm_ = new JavaVMExt(this, runtime_options); 已经明显得出来了。 那另外以个JniEnv呢?

其实是在Thread::Attach里面。

Thread* Thread::Attach(const char* thread_name, bool as_daemon, jobject thread_group,
                       bool create_peer) {
  Runtime* runtime = Runtime::Current();
...
      Runtime::Current()->StartThreadBirth();
      self = new Thread(as_daemon);
      bool init_success = self->Init(runtime->GetThreadList(), runtime->GetJavaVM());
      Runtime::Current()->EndThreadBirth();
      if (!init_success) {
        delete self;
        return nullptr;
      }
...
  }

如果Thread 还没有建立,会新建立一个然后Init。

bool Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm, JNIEnvExt* jni_env_ext) {
 ...
    tlsPtr_.jni_env = JNIEnvExt::Create(this, java_vm);
    if (tlsPtr_.jni_env == nullptr) {
      return false;
    }
  }

...
  return true;
}

好的jni_env 也有了。

然后总结下,假设一个例子,JNIEnv调用一个FindClass接口,最终会调用到JNIEnvExt来对不对,不对,应该是function->

struct _JNIEnv {
    const struct JNINativeInterface* functions;

#if defined(__cplusplus)

    jint GetVersion()
    { return functions->GetVersion(this); }

    jclass FineClass(const char *name, )
    { return functions->FineClass(this, name, ..); }

所以还要继续往下分析

struct JNIEnvExt : public JNIEnv {
}

是继承JNIEnv的。就看cpp中哪里赋值了。

JNIEnvExt* JNIEnvExt::Create(Thread* self_in, JavaVMExt* vm_in) {
  std::unique_ptr<JNIEnvExt> ret(new JNIEnvExt(self_in, vm_in));
  if (CheckLocalsValid(ret.get())) {
    return ret.release();
  }
  return nullptr;
}

JNIEnvExt::JNIEnvExt(Thread* self_in, JavaVMExt* vm_in)
    : self(self_in),
...
      monitors("monitors", kMonitorsInitial, kMonitorsMax) {
  functions = unchecked_functions = GetJniNativeInterface();
...
}

在构造函数里赋值了。

const JNINativeInterface* GetJniNativeInterface() {
  return &gJniNativeInterface;
}
const JNINativeInterface gJniNativeInterface = {
  nullptr,  // reserved0.
  nullptr,  // reserved1.
  nullptr,  // reserved2.
  nullptr,  // reserved3.
  JNI::GetVersion,
  JNI::DefineClass,
  JNI::FindClass,
  JNI::FromReflectedMethod,
  JNI::FromReflectedField,
  JNI::ToReflectedMethod,
  JNI::GetSuperclass,
  JNI::IsAssignableFrom,
  JNI::ToReflectedField,
  JNI::Throw,
  JNI::ThrowNew,
  }
art/runtime/jni_internal.cc

OK,最终定义在这个全局变量里面。这样如果以后上层调用FindClass,直接到这个文件,这个全局变量开始。

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: