zoukankan      html  css  js  c++  java
  • Dalvik虚拟机总结

        一、Dalvik虚拟机启动

        在启动Zygote进程时,会启动Dalvik虚拟机,完毕以下几件事:

        1. 创建了一个Dalvik虚拟机实例; 

        2. 载入了Java核心类及注冊其JNI方法; 

        3. 为主线程的设置了一个JNI环境; 

        4. 注冊了Android核心类的JNI方法。

    void AndroidRuntime::start(const char* className, const bool startSystemServer)
    {
        ......
    
        /* start the virtual machine */
        if (startVm(&mJavaVM, &env) != 0)
            goto bail;
    
        /*
         * Register android functions.
         */
        if (startReg(env) < 0) {
            LOGE("Unable to register all android natives
    ");
            goto bail;
        }
    
        ......
    
        /*
         * Start VM.  This thread becomes the main thread of the VM, and will
         * not return until the VM exits.
         */
        jclass startClass;
        jmethodID startMeth;
    
        slashClassName = strdup(className);
        for (cp = slashClassName; *cp != ''; cp++)
            if (*cp == '.')
                *cp = '/';
    
        startClass = env->FindClass(slashClassName);
        if (startClass == NULL) {
            LOGE("JavaVM unable to locate class '%s'
    ", slashClassName);
            /* keep going */
        } else {
            startMeth = env->GetStaticMethodID(startClass, "main",
                "([Ljava/lang/String;)V");
            if (startMeth == NULL) {
                LOGE("JavaVM unable to find main() in '%s'
    ", className);
                /* keep going */
            } else {
                env->CallStaticVoidMethod(startClass, startMeth, strArray);
                ......
            }
        }
    
        LOGD("Shutting down VM
    ");
        if (mJavaVM->DetachCurrentThread() != JNI_OK)
            LOGW("Warning: unable to detach main thread
    ");
        if (mJavaVM->DestroyJavaVM() != 0)
            LOGW("Warning: VM did not shut down cleanly
    ");
    
        ......
    }


        二、第一次解释运行java程序。env->CallStaticVoidMethod(startClass, startMeth, strArray)终于会解释运行com.android.internal.os.ZygoteInit类的静态成员函数main

        參考Dalvik虚拟机的运行过程分析。随着方法调用的不同,不断运行不同的GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall, u2 count, u2 regs)或者GOTO_TARGET(returnFromMethod)等等。去解释运行java程序。


        三、Zygote进程等待来在SystemServer的请求,来创建应用程序进程

        static native int selectReadable(FileDescriptor[] fds) throws IOException;

        此时dalvik虚拟机不是解释运行java程序,而是调用C/C++程序的入口地址,直接运行C/C++代码。因为在第一步中已经注冊Android核心JNI,所以能够直接调用,请看考以下的第六点。


        四、Zygote进程创建SystemServer进程

    pid = Zygote.forkSystemServer(
                        parsedArgs.uid, parsedArgs.gid,
                        parsedArgs.gids, debugFlags, null,
                        parsedArgs.permittedCapabilities,
                        parsedArgs.effectiveCapabilities);
     if (pid == 0) {
                handleSystemServerProcess(parsedArgs);//运行了com.android.server.SystemServer中main方法
            }
       本质上使用fork来创建一个新的进程。Zygote进程在启动是创建的Dalvik虚拟机实例和主线程的环境,使用COW的方式共享。其它两点因为是仅仅读,共享就可以。

       返回到pid==0,此时已经是SystemServer进程的Davlik虚拟机主线程的环境来解释运行handleSystemServerProcess。


        五、SystemServer进程调用Process.start。通过Socket请求Zygote进程来创建应用程序进程

    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
                        parsedArgs.gids, parsedArgs.debugFlags, rlimits);
    if (pid == 0) {
                // in child
                handleChildProc(parsedArgs, descriptors, newStderr);//android.app.ActivityThread中的main函数
                // should never happen
                return true;
            }
        和第四点的描写叙述一样。


        六、应用程序进程注冊JNI。并运行JNI方法。

        注冊过程请參考Dalvik虚拟机JNI方法的注冊过程分析,会调用JNI_OnLoad获取主线程的Dalvik虚拟机环境JNIENV,并调用了dvmSetNativeFunc设置了navtiveFunc。

        当运行到JNI方法时。会调用*method->nativeFunc。不是解释运行,是直接在机器上运行。    

    void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
        bool fromJni, JValue* pResult, va_list args)
    {
        ......
    
        if (dvmIsNativeMethod(method)) {
            TRACE_METHOD_ENTER(self, method);
            /*
             * Because we leave no space for local variables, "curFrame" points
             * directly at the method arguments.
             */
            (*method->nativeFunc)(self->curFrame, pResult, method, self);
            TRACE_METHOD_EXIT(self, method);
        } else {
            dvmInterpret(self, method, pResult);
        }
    
        ......
    }
        当假设想在JNI方法中调用Java方法,必须得有当前线程的Davlik虚拟机环境JNIENV,比如:

    (*jniEnv)->CallVoidMethod(jniEnv, mTestProvider, sayHello,jstrMSG);
        和第二点一样,必须由Davlik虚拟机去解释运行Java方法。


        七、应用程序进程,Java中开启一个线程,Thread.start

        參考Dalvik虚拟机进程和线程的创建过程分析,使用clone创建了一个新的线程。和进程(主线程)共享进程空间。因为此线程没有Dalvik虚拟机环境JNIENV,所以要为该进程设置虚拟机环境。有了环境后就能够在解释运行Java代码了。例如以下:

    dvmCallMethod(self, run, self->threadObj, &unused);  

        八、应用程序进程。C/C++中开启一个线程
        1、.仅仅运行C/C++代码的Native线程的创建过程:

        不会创建该线程的Dalvik虚拟机环境JNIENV。

        2、能同一时候运行C/C++代码和Java代码的Native线程的创建过程

        须要创建该线程的Dalvik虚拟机环境JNIENV,就能够解释运行Java代码了。


  • 相关阅读:
    asp读书笔记(二)内置对象
    网上收集的关于iframe的自适应高度代码js的
    第一遇到地震,虽然小点
    给网友写的控制页面元素高度的代码(js)
    给用户控件添加可枚举的属性
    标记(Tagging)能给网站带来的7大益处
    代码最重要的读者不再是编译器、解释器或者电脑,而是人!
    亚洲超大数据库会议(XLDB Asia 2012)
    每年15万美元!这是开发人员解决构造问题的总成本!
    华章IT图书书讯(2012年第7期)
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7138118.html
Copyright © 2011-2022 走看看