From the previous section, we can know the Dalvik Virtual Machine entry point and the function for creating virtual machines. This section continues to analyze the code snippets of the runtime class calling virtual machines. We need to figure out how to run Java's zygoteinit class, what kind of interface call is provided by the Dalvik Virtual Machine. The runtime class code is as follows:
/* Start the Virtual Machine */
If (startvm (& mjavavm, & env )! = 0)
Goto bail;
This section describes how to create a virtual machine and prepare all the environments that run the DEX code.
/*
* Register Android functions.
*/
If (starregulatory (ENV) <0 ){
LogE ("unable to register all androidnatives/N ");
Goto bail;
}
This section registers all local methods provided by Android. The so-called local methods are actually compared to the methods defined in Java, such as the binary running methods provided by C or C ++.
/*
* We want to call main () with a stringarray with arguments in it.
* At present we only have one argument, theclass name. Create
* Array to hold it.
*/
Jclass stringclass;
Jobjectarray strarray;
Jstring classnamestr;
Jstring startsystemserverstr;
Stringclass = env-> findclass ("Java/lang/string ");
Assert (stringclass! = NULL );
Strarray = env-> newobjectarray (2, stringclass, null );
Assert (strarray! = NULL );
Classnamestr = env-> newstringutf (classname );
Assert (classnamestr! = NULL );
Env-> setobjectarrayelement (strarray, 0, classnamestr );
Startsystemserverstr = env-> newstringutf (startsystemserver?
"True": "false ");
Env-> setobjectarrayelement (strarray, 1, startsystemserverstr );
The main function of this Code is to convert the classname parameter of the type parameter to the parameter used to call the method in the virtual machine, that is, convert it to the strarray representation, and add multiple parameters.
/*
* Start VM. This thread becomes the mainthread of the VM, and will
* Not return until the VM exits.
*/
Jclass startclass;
Jmethodid startmeth;
Slashclassname = strdup (classname );
This line of code is the copy class name.
For (Cp = slashclassname; * CP! = '/0'; CP ++)
If (* CP = '.')
* CP = '/';
In this Code, the class name com. Android. Internal. OS. zygoteinit is converted to com/Android/Internal/OS/zygoteinit. Why is this conversion method required? In fact, I think it is not the directory representation in Linux? Yes, it is to change the class point connector to the directory method, which can find the code file to be executed in the corresponding directory.
Logd ("caijs Add: JavaVM load class '% s'/N", slashclassname );
Startclass = env-> findclass (slashclassname );
If (startclass = NULL ){
LogE ("JavaVM unable to locate class '% s'/N", slashclassname );
/* Keep going */
} Else {
This code mainly uses the class directory structure COM/Android/Internal/OS/zygoteinit to find the class code, and stores it in the startclass variable. The most important method provided by the Dalvik virtual machine is the findclass method interface. This interface is powerful, as long as the directory structure of the class is provided, you can find the corresponding Execution Code, so that you can find the method entry related to the class before the virtual machine interpreter can execute. Therefore, you must understand and analyze the implementation of this interface later.
Startmeth = env-> getstaticmethodid (startclass, "Main ",
"([Ljava/lang/string;) V ");
If (startmeth = NULL ){
LogE ("JavaVM unable to findmain () in '% s'/N", classname );
/* Keep going */
} Else {
This code is the ID of the method entry point. Based on the class code found above, call the getstaticmethodid interface with the method name "Main" to find the method ID. This method ID is used to run this method on the following virtual machine, because there are many methods in a class, each method has an ID, only through this ID can you find the corresponding method to run. In this Code, there is a special point, that is, the last parameter "([ljava/lang/string;) V" of the getstaticmethodid method ". This parameter is a string, but the content is arranged strangely. In fact, it is an encoding for the function return value and parameters. This encoding is called the JNI field descriptor (javanative
Interface FIelddescriptors).
Logd ("caijs Add: JavaVM findmain () in '% s'/N", classname );
Env-> callstaticvoidmethod (startclass, startmeth, strarray );
This line of code mainly calls the Virtual Machine Interface callstaticvoidmethod to run the main method in the com. Android. Internal. OS. zygoteinit class. In the Android system, after running this class of code, it will no longer return. This process will become the main process of the virtual machine, and this virtual machine will become a virtual machine that mainly runs the zygoteinit class, virtual machines of other applications are cloned from this virtual machine to quickly generate a derived Virtual Machine. Each application has a virtual machine robust and secure.
# If0
If (env-> exceptioncheck ())
Threadexituncaughtexception (ENV );
# Endif
}
}
Logd ("shutting down VM/N ");
If (mjavavm-> detachcurrentthread ()! = Jni_ OK)
Logw ("Warning: Unable to detach mainthread/N ");
If (mjavavm-> destroyjavavm ()! = 0)
Logw ("Warning: VM did not shut downcleanly/N ");
This code is called when all virtual machines are disabled, and basically this code is not called.
Bail:
Free (slashclassname );
This line of code is called when an error occurs during initialization.
}
In this section, we learned the three major interface functions of the davlik Virtual Machine: findclass, getstaticmethodid, and callstaticvoidmethod. In fact, it is easy to understand, that is, find the corresponding Java class code through the findclass interface, and then find the corresponding method ID using the getstaticmethodid interface in this class code, finally, you can run the corresponding method code through the callstaticvoidmethod interface to complete the Java code and run it on the virtual machine.