Dalvik開始

以下はAndroid4.0.4に基づいています

受精卵で開始

if(zygote){
  runtime.start("com.android.internal.os.ZygoteInit", startSystemServer ? "start-system-server" : "");
}

使用JNI機構を(文字列[])メインボイド完全実行com.android.internal.os.ZygoteInit @開始、runtime.start中)のDalvikのプロセス(にある接合体を開始


AndroidRuntime.cpp @スタート()では、キーはこれらの点があります

JavaVM* AndroidRuntime::mJavaVm = NULL;

void AndroidRuntime::start(const char* className, const char* options){
  ...
  JNIEnv* env;
  startVm(&mJavaVm, &env);
  onVmCreated(env);
  startReg(evn);
  ..
  //然后 JNI 执行 className 对应的 main 方法
}

データ構造定義を見て、私たちはJavaVMの、JNIEnvの、JavaVmExtに焦点を当てる必要があります

struct JNIEnvExt {
  const struct JNINativeInterface* funTable;
  const struct JNINativeInterface* baseFuncTable;

  u4 envThreadId;
  Thread* self;
  int critical;
  struct JNIEnvExt* prev;
  struct JNIEnvExt* next;
}

struct JavaVmExt{
  const struct JNIInvokeInterface* funcTable;
  const struct JNIInvokeInterface* baseFuncTable;

  JNIEnvExt* envList;
  pthread_mutex_t envListLock;
}  

typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvoleInterface* JavaVM;

//
/*static*/ JNIEnv* AndroidRuntime::getJNIEnv()
{
    JNIEnv* env;
    JavaVM* vm = AndroidRuntime::getJavaVM();
    assert(vm != NULL);

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
        return NULL;
    return env;
}

Dalvik内で見ることができるデータ構造によれば、限り訪問はJNIEnvのメモリ空間を超えないよう、JNIEnvの使用に強いことJNIEnvExt。同様に限り、訪問はJavaVMの定義されたメモリ空間を超えないよう、使用するJavaVMのに強いことJavaVMExt。もちろん、これは内部変換にもあります。最後に、記事を見て


JNI環境ですJavaVmExtに代わってのDalvik仮想マシンインスタンスで、JNIEnvExtに代わって、各スレッドは、JNI環境に関連した独自のを持っており、JavaVmExtは、二本鎖形態でJNI環境を保存します。

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv){
  ...
  //利用 property_get()方法解析 Dalvik 虚拟机的启动项
  ...
  //获得Dalvik 启动项后,开始创建虚拟机实例 JavVmExt
  JNI_CreateJavaVM(pJavaVm, pEnv, &initArgs);
}
@.../dalvik/vm/Jni.cpp
jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args){
  //参数
  const JavaVMInitArgs* args = (JavaVMInitArgs*) vm_arsg;
  //检查版本号
  if(args->version < JNI_VERSION_1_2){
    return JNI_EVERSION;
  }
  //gDvm 的一个全局变量,保存着 Dalvik 的所有信息。在此处初始化内存
  memset(&gDvm, 0, sizeof(gDvm));
   //为 Dalvik 实例分配内存
  JavaVMExt* pVM = (JavaVMExt*) malloc(sizeof(JavaVMExt));
  //初始化内存
  memset(pVM, 0, sizeof(JavaVMExt));
  //函数表
  pVM->funcTable = &gInvokeInterface;
  ...
  //参数处理
  ...
  //将 Dalvik 实例 JavaVMExt 作为全局变量
  gDvmJni.jniVM = (JavaVM*) pVM;
  //初始化虚拟机环境,这里参数 NULL 表示初始化Dalvik主线程
  JNIEnvExt* pEnv = (JNIEnvExt*) dvmCreateJNIEnv(NULL);
  gDvm.initializing = true;
  //虚拟机初始化,初始化了各个模块
  //包括线程管理,类加载,解释器,内存管理,即时编译,本地方法调用,反射机制实现,调试支撑等
  std::string status = dvmStartup(argc, argv.get(), args->ignoreUnrecognized, (JNIEnv*)pEnv);
}

 //主要是创建一个 JNIEnv,设置 JNI 方法表,并且添加到 JavaVMExt->envList
JNIEnv* dvmCreateJNIEnv(Thread* self){
  //全局 Dalvik 实例
  JavaVMExt* vm = (JavaVMExt*) gDvmJni.jniVm;
  //JNI 环境分配内存
  JNIEnvExt* newEnv = (JNIEnvExt*) calloc(1, sizeof(JNIEnvExt));
  //本地接口函数表,形如 FinClass( )等 JNI 函数的函数入口表
  newEnv->funcTable = &gNativeInterface;
  if(self != NULL){
    //在这里说明是初始化非主线程,将 JNI 环境关联线程
    dvmSetJniEnvThreadId((JNIEnv*)newEnv, self);
  }else{
    //想要关联的是主线程,先设置值,表示延后关联
    newEnv->envThreadId = 0x77777775;
    newEnv->self = (Thread*)0x7777779;
  }
  ...
  // 将自身 JNIEnv 添加到 JavaVM 的 JNI 列表
  newEnv->next = vm->envList;
  if(vm->envList == NULL){
      vm->envList  = newEnv;
  }else{
    vm->envList->prev = newEnv;
  }
  vm->envList = newEnv;
  return (JNIEnv*) newEnv;
}

関数テーブル

//被赋值到 JNIEnvExt.funcTable
static const struct JNINativeInterface gNativeInterface = {
    NULL,
    NULL,
    NULL,
    NULL,

    GetVersion,

    DefineClass,
    FindClass,

    FromReflectedMethod,
    FromReflectedField,
    ToReflectedMethod,

    GetSuperclass,
    IsAssignableFrom,

    ToReflectedField,

    Throw,
    ThrowNew,
    ExceptionOccurred,
    ExceptionDescribe,
    ExceptionClear,
    FatalError,

    PushLocalFrame,
    PopLocalFrame,

    NewGlobalRef,
    DeleteGlobalRef,
    DeleteLocalRef,
    IsSameObject,
    NewLocalRef,
    EnsureLocalCapacity,

    AllocObject,
    NewObject,
    NewObjectV,
    NewObjectA,

    GetObjectClass,
    IsInstanceOf,

    GetMethodID,

    CallObjectMethod,
    CallObjectMethodV,
    CallObjectMethodA,
    CallBooleanMethod,
    CallBooleanMethodV,
    CallBooleanMethodA,
    CallByteMethod,
    CallByteMethodV,
    CallByteMethodA,
    CallCharMethod,
    CallCharMethodV,
    CallCharMethodA,
    CallShortMethod,
    CallShortMethodV,
    CallShortMethodA,
    CallIntMethod,
    CallIntMethodV,
    CallIntMethodA,
    CallLongMethod,
    CallLongMethodV,
    CallLongMethodA,
    CallFloatMethod,
    CallFloatMethodV,
    CallFloatMethodA,
    CallDoubleMethod,
    CallDoubleMethodV,
    CallDoubleMethodA,
    CallVoidMethod,
    CallVoidMethodV,
    CallVoidMethodA,

    CallNonvirtualObjectMethod,
    CallNonvirtualObjectMethodV,
    CallNonvirtualObjectMethodA,
    CallNonvirtualBooleanMethod,
    CallNonvirtualBooleanMethodV,
    CallNonvirtualBooleanMethodA,
    CallNonvirtualByteMethod,
    CallNonvirtualByteMethodV,
    CallNonvirtualByteMethodA,
    CallNonvirtualCharMethod,
    CallNonvirtualCharMethodV,
    CallNonvirtualCharMethodA,
    CallNonvirtualShortMethod,
    CallNonvirtualShortMethodV,
    CallNonvirtualShortMethodA,
    CallNonvirtualIntMethod,
    CallNonvirtualIntMethodV,
    CallNonvirtualIntMethodA,
    CallNonvirtualLongMethod,
    CallNonvirtualLongMethodV,
    CallNonvirtualLongMethodA,
    CallNonvirtualFloatMethod,
    CallNonvirtualFloatMethodV,
    CallNonvirtualFloatMethodA,
    CallNonvirtualDoubleMethod,
    CallNonvirtualDoubleMethodV,
    CallNonvirtualDoubleMethodA,
    CallNonvirtualVoidMethod,
    CallNonvirtualVoidMethodV,
    CallNonvirtualVoidMethodA,

    GetFieldID,

    GetObjectField,
    GetBooleanField,
    GetByteField,
    GetCharField,
    GetShortField,
    GetIntField,
    GetLongField,
    GetFloatField,
    GetDoubleField,
    SetObjectField,
    SetBooleanField,
    SetByteField,
    SetCharField,
    SetShortField,
    SetIntField,
    SetLongField,
    SetFloatField,
    SetDoubleField,

    GetStaticMethodID,

    CallStaticObjectMethod,
    CallStaticObjectMethodV,
    CallStaticObjectMethodA,
    CallStaticBooleanMethod,
    CallStaticBooleanMethodV,
    CallStaticBooleanMethodA,
    CallStaticByteMethod,
    CallStaticByteMethodV,
    CallStaticByteMethodA,
    CallStaticCharMethod,
    CallStaticCharMethodV,
    CallStaticCharMethodA,
    CallStaticShortMethod,
    CallStaticShortMethodV,
    CallStaticShortMethodA,
    CallStaticIntMethod,
    CallStaticIntMethodV,
    CallStaticIntMethodA,
    CallStaticLongMethod,
    CallStaticLongMethodV,
    CallStaticLongMethodA,
    CallStaticFloatMethod,
    CallStaticFloatMethodV,
    CallStaticFloatMethodA,
    CallStaticDoubleMethod,
    CallStaticDoubleMethodV,
    CallStaticDoubleMethodA,
    CallStaticVoidMethod,
    CallStaticVoidMethodV,
    CallStaticVoidMethodA,

    GetStaticFieldID,

    GetStaticObjectField,
    GetStaticBooleanField,
    GetStaticByteField,
    GetStaticCharField,
    GetStaticShortField,
    GetStaticIntField,
    GetStaticLongField,
    GetStaticFloatField,
    GetStaticDoubleField,

    SetStaticObjectField,
    SetStaticBooleanField,
    SetStaticByteField,
    SetStaticCharField,
    SetStaticShortField,
    SetStaticIntField,
    SetStaticLongField,
    SetStaticFloatField,
    SetStaticDoubleField,

    NewString,

    GetStringLength,
    GetStringChars,
    ReleaseStringChars,

    NewStringUTF,
    GetStringUTFLength,
    GetStringUTFChars,
    ReleaseStringUTFChars,

    GetArrayLength,
    NewObjectArray,
    GetObjectArrayElement,
    SetObjectArrayElement,

    NewBooleanArray,
    NewByteArray,
    NewCharArray,
    NewShortArray,
    NewIntArray,
    NewLongArray,
    NewFloatArray,
    NewDoubleArray,

    GetBooleanArrayElements,
    GetByteArrayElements,
    GetCharArrayElements,
    GetShortArrayElements,
    GetIntArrayElements,
    GetLongArrayElements,
    GetFloatArrayElements,
    GetDoubleArrayElements,

    ReleaseBooleanArrayElements,
    ReleaseByteArrayElements,
    ReleaseCharArrayElements,
    ReleaseShortArrayElements,
    ReleaseIntArrayElements,
    ReleaseLongArrayElements,
    ReleaseFloatArrayElements,
    ReleaseDoubleArrayElements,

    GetBooleanArrayRegion,
    GetByteArrayRegion,
    GetCharArrayRegion,
    GetShortArrayRegion,
    GetIntArrayRegion,
    GetLongArrayRegion,
    GetFloatArrayRegion,
    GetDoubleArrayRegion,
    SetBooleanArrayRegion,
    SetByteArrayRegion,
    SetCharArrayRegion,
    SetShortArrayRegion,
    SetIntArrayRegion,
    SetLongArrayRegion,
    SetFloatArrayRegion,
    SetDoubleArrayRegion,

    RegisterNatives,
    UnregisterNatives,

    MonitorEnter,
    MonitorExit,

    GetJavaVM,

    GetStringRegion,
    GetStringUTFRegion,

    GetPrimitiveArrayCritical,
    ReleasePrimitiveArrayCritical,

    GetStringCritical,
    ReleaseStringCritical,

    NewWeakGlobalRef,
    DeleteWeakGlobalRef,

    ExceptionCheck,

    NewDirectByteBuffer,
    GetDirectBufferAddress,
    GetDirectBufferCapacity,

    GetObjectRefType
};
//赋值到JavaVMExt.funcTable
static const struct JNIInvokeInterface gInvokeInterface = {
    NULL,
    NULL,
    NULL,

    DestroyJavaVM,
    AttachCurrentThread,
    DetachCurrentThread,

    GetEnv,

    AttachCurrentThreadAsDaemon,
};
3012162-742c23ace92a997b.png
Dalvik開始

例:JavaのJNI関数を呼び出すときに、ルックアップJCLASS時間に使用されenv-> FindClassが();
このgNativeInterface(Jni.cpp)で具体定義)(FinClass下記参照関数のエントリ、およびその他のJNI関数また、実装はJni.cppで見ることができます

static jclass FindClass(JNIEnv* env, const char* name) {
    ScopedJniThreadState ts(env);

    const Method* thisMethod = dvmGetCurrentJNIMethod();
    assert(thisMethod != NULL);

    Object* loader;
    Object* trackedLoader = NULL;
    if (ts.self()->classLoaderOverride != NULL) {
        /* hack for JNI_OnLoad */
        assert(strcmp(thisMethod->name, "nativeLoad") == 0);
        loader = ts.self()->classLoaderOverride;
    } else if (thisMethod == gDvm.methDalvikSystemNativeStart_main ||
               thisMethod == gDvm.methDalvikSystemNativeStart_run) {
        /* start point of invocation interface */
        if (!gDvm.initializing) {
            loader = trackedLoader = dvmGetSystemClassLoader();
        } else {
            loader = NULL;
        }
    } else {
        loader = thisMethod->clazz->classLoader;
    }

    char* descriptor = dvmNameToDescriptor(name);
    if (descriptor == NULL) {
        return NULL;
    }
    ClassObject* clazz = dvmFindClassNoInit(descriptor, loader);
    free(descriptor);

    jclass jclazz = (jclass) addLocalReference(ts.self(), (Object*) clazz);
    dvmReleaseTrackedAlloc(trackedLoader, ts.self());
    return jclazz;
}

同様に、()AndroidRuntime :: getJNIEnv、そこVM-> GETENV()関数、gInvokeInterface(Jni.cpp)の関数のエントリを参照して見られます。

ます。https://www.jianshu.com/p/7ecf0d314da8で再現

おすすめ

転載: blog.csdn.net/weixin_34050427/article/details/91311533