Dalvik虚拟机JNI方法的注册过程分析

这些Bridage函数实际上仍然不是直接调用地调用JNI方法的,

这是因为Dalvik虚拟机是可以运行在各种不同的平台之上,而每一种平台可能都定义有自己的一套函数调用规范,
也就是所谓的ABI(Application Binary Interface),这是一个API(Application Programming Interface)不同的概念。
ABI是在二进制级别上定义的一套函数调用规范,

例如参数是通过寄存器来传递还是堆栈来传递,而API定义是一个应用程序编程接口规范。

换句话说,API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译 ,

而ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。 
寄存器传递,堆栈传递,  

void dvmSetNativeFunc(Method* method, DalvikBridgeFunc func,
    const u2* insns)
{
    ......
 
    if (insns != NULL) {
        /* update both, ensuring that "insns" is observed first */
        method->insns = insns;
        android_atomic_release_store((int32_t) func,
            (void*) &method->nativeFunc);
    } else {
        /* only update nativeFunc */
        method->nativeFunc = func;
    }
 
    ......
}

      假设在前面的Step 11中选择的Bridge函数为dvmCallJNIMethod_general,并且结合前面Dalvik虚拟机的运行过程分析一文,
我们就可以得到Dalvik虚拟机在运行过程中调用JNI方法的过程:

        1. 调用函数dvmCallJNIMethod_general,执行一些必要的准备工作;

        2. 函数dvmCallJNIMethod_general再调用函数dvmPlatformInvoke来以统一的方式来调用对应的JNI方法;

        3. 函数dvmPlatformInvoke通过libffi库来调用对应的JNI方法,以屏蔽Dalvik虚拟机运行在不同目标平台的细节。

 至此,我们就分析完成Dalvik虚拟机JNI方法的注册过程了。这样,我们就打通了Java代码和Native代码之间的道路。
 实际上,很多Java和Android核心类的功能都是通过本地操作系统提供的系统调用来完成的,
 例如,Zygote类的成员函数forkAndSpecialize最终是通过Linux系统调用fork来创建一个Android应用程序进程的,
 又如,Thread类的成员函数start最终是通过pthread线程库函数pthread_create来创建一个Android应用程序线程的。

Zygote  forkAndSpecialize   fork  Android   应用进程

Thread  start  pthread pthread_create Android  创建Android应用线程
 

 

Dalvik虚拟机源码初探

           一. Dalvik虚拟机进程的创建过程

  int pid = Process.start("android.app.ActivityThread",  
                mSimpleProcessManagement ? app.processName : null, uid, uid,  
                gids, debugFlags, null);  


         它调用了Process.start函数开始为应用程序创建新的进程,注意,它传入一个第一个参数为"android.app.ActivityThread",
        这就是进程初始化时要加载的Java类了,把这个类加载到进程之后,就会把它里面的静态成员函数main作为进程的入口点,
        后面我们会看到。

  Dalvik虚拟机进程实际上就是通常我们所说的Android应用程序进程。从前面Android应用程序进程启动过程的源代码分析一文可以知道,Android应用程序进程是由ActivityManagerService服务通过android.os.Process类的静态成员函数start来请求Zygote进程创建的,而Zyogte进程最终又是通过dalvik.system.Zygote类的静态成员函数forkAndSpecialize来创建该Android应用程序进程的。因此,接下来我们就从dalvik.system.Zygote类的静态成员函数forkAndSpecialize开始分析Dalvik虚拟机进程的创建过程,如图1所示:


    pid = fork();

由Zygote进程创建出来的Android应用程序进程是不具有任何的Root用户特权的。
        
        对于函数forkAndSpecializeCommon的实现,还有两个地方是需要注意的。
        forkAndSpecializeCommon   
        
               第一个地方是只有Zygote进程才有权限创建System进程和Android应用程序进程
               
               
               Zygote进程在启动运行在它里面的Dalvik虚拟机的时候,gDvm.zygote的值会等于true,
               
               这时候函数forkAndSpecializeCommon才可以使用系统调用fork来创建一个新的进程
        
        Dalvik虚拟机除了可以执行Java代码之外,还可以执行Native代码,也就是C/C
        
        Java和Android核心类库(dex文件)及其JNI方法(so文件)
        
    java Android dex文件)及其JNI方法(so文件)  
    
    都会一直在Zygote进程、System进程和Android应用程序进程中进行共享。
        此外,运行在Zygote进程中的Dalvik虚拟机开始的时候也会与System进程和Android应用程序进程一起共享,
    
    但是由于上述的COW机制,在必要的时候,System进程和Android应用程序进程还是会复制一份出来的,
    
    从而使得它们都具有独立的Dalvik虚拟机实例。

    调用函数 dvmGcStartupAfterZygote来进行一次GC。
    dvmGcStartupAfterZygote来进行一次GC。 GC
    
    一个Dalvik虚拟机进程实际上就是一个Linux进程。

   二. Dalvik虚拟机线程的创建过程

Dalvik虚拟机源码初探

 

 

           
           在Java代码中,我们可以通过java.lang.Thread类的成员函数start来创建一个Dalvik虚拟机线程

public class Thread implements Runnable {
    ......
 
    public synchronized void start() {
        if (hasBeenStarted) {
            throw new IllegalThreadStateException("Thread already started."); // TODO Externalize?
        }
 
        hasBeenStarted = true;
 
        VMThread.create(this, stackSize);
    }
 
    ......
}

VMThread.create


class VMThread
{
    ......
 
    native static void create(Thread t, long stacksize);
 
    ......
}


bool dvmCreateInterpThread(Object* threadObj, int reqStackSize)
{
    pthread_attr_t threadAttr;
    pthread_t threadHandle;
    ......
    Thread* newThread = NULL;
    ......
    int stackSize;
    ......
 
    if (reqStackSize == 0)
        stackSize = gDvm.stackSize;
    else if (reqStackSize < kMinStackSize)
        stackSize = kMinStackSize;
    else if (reqStackSize > kMaxStackSize)
        stackSize = kMaxStackSize;
    else
        stackSize = reqStackSize;
 
    pthread_attr_init(&threadAttr);
    pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
    ......
 
    newThread = allocThread(stackSize);
    ......
 
    newThread->threadObj = threadObj;
    ......
 
    int cc = pthread_create(&threadHandle, &threadAttr, interpThreadStart,
            newThread);
    ......
 
    while (newThread->status != THREAD_STARTING)
        pthread_cond_wait(&gDvm.threadStartCond, &gDvm.threadListLock);
    ......
 
    newThread->next = gDvm.threadList->next;
    if (newThread->next != NULL)
        newThread->next->prev = newThread;
    newThread->prev = gDvm.threadList;
    gDvm.threadList->next = newThread;
    ......
 
    newThread->status = THREAD_VMWAIT;
    pthread_cond_broadcast(&gDvm.threadStartCond);
    ......
 
    return true;
}


pthread_cond_wait(&gDvm.threadStartCond,&gDvm.threadListLock);


newThread.next= gDvm.threadList.next

newThread.next.prev = newThread

newThread.prev = gDvm.threadList
gDvm.threadList.new = newThread
newThread.status = THREAD_VMWAIT
pthread_cond_broadcast(&gDvm.threadStartCond)

 

 

相关文章: