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虚拟机进程的创建过程
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虚拟机线程的创建过程
在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)