- 浏览: 225928 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
sfshine:
非常好非常好
Android 窗口管理 -
mthhk:
...
android3.0之Fragment(碎片)基础 -
FrankHB1989:
“C/C++标准不会保证这样的代码一定不会出错”的依据?你要说 ...
Duff's Device -
2006003845:
请问知道 刚体之间怎么不碰撞嘛 ?相互穿插
JBOX2D分析
Android深入浅出之Zygote(转)
- 博客分类:
- Android
[size=xx-small]Android深入浅出之Zygote
一 目的
zygote,是Android搞出来的一个东西。网上讲这个的也非常多。第一次看到这个名字我就挺郁闷,想干嘛这是?Linux下名字都取得挺通俗易懂,深得人心。zygote?不就想模仿Linux下的fork吗?个人觉得Google取名字挺怪,包括Google本身。
不管怎样,Zygote依然是Android系统的核心,zygote是受精卵的意思,可以认为是Android framework大家族的祖先!我们本节的目的是描述下zygote的来龙去脉,顺便揭露下它的短处,以后大家可以对症下药,变异一个更加优良的品种。
二 Zygote
zygote本身是一个应用层的程序,和驱动,内核模块之类的没点关系。这下大家放心点了吧?zygote的启动由linux的祖先init启动。这个在init分析中提过。这里就不说了。
zygote,ps中看到的进程名叫zygote,其最初的名字是app_process,通过直接调用pctrl把名字给改成了”zygote”。不过不影响我们分析。
zygote的代码在framework/base/cmds/app_process/App_main.cpp中。我们一步步来看。
既然是应用程序,直接看main咯。[/size]
int main(int argc, const char* const argv[])
{
//参数很重要啊,还记得init分析吗?
//恩,这几个参数就是:(一定要记住我们的情景分析方法!)
//zygote /system/bin/app_process
//-Xzygote /system/bin --zygote --start-system-server
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime;
//AppRuntime是个什么玩意儿?addVmArguments?好像和虚拟机有点关系喔
int i = runtime.addVmArguments(argc, argv);
[--->AppRuntime]
class AppRuntime : public AndroidRuntime
从AndroidRuntime中派生而来,是和dalvik交互的一个方便类,这里先不说了。
[---->main]
...
int i = runtime.addVmArguments(argc, argv);
....
if (i < argc) {
arg = argv[i++];
if (0 == strcmp("--zygote", arg)) {
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
//废话,根据我们的参数,startSystemServer=true
setArgv0(argv0, "zygote");
//改名字,不知道windows下的怎么改、linux下的可以用pctrl系统调用
set_process_name("zygote");
//start?记住我们的参数
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
}
} else {
return 10;
}
FT,app_main还是很简单的,但是runtime.start看起来不简单啊,传进去的那个参数
“com.android.internal.os.ZygoteInit“挺像java类的命名规则。
2.1 AppRuntime
好了,代码进入到runtime.start("com.android.internal.os.ZygoteInit",true)了。source insight直接进去看看。代码在framework/base/core/jni/AppRuntime.cpp中。
[--->void AndroidRuntime::start()]
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
LOGD("/n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<</n");
char* slashClassName = NULL;
char* cp;
JNIEnv* env;
//linux下signal的处理,没什么好说的
blockSigpipe();
//设置环境变量ANDROID_ROOT为/system
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
setenv("ANDROID_ROOT", rootDir, 1);
}
/*启动虚拟机*/
if (startVm(&mJavaVM, &env) != 0)
goto bail;
启动虚拟机,和JAVA有关系了吧?Android最重要的sdk都是java,那虚拟机这部分肯定要进去看看的。
[--->int AndroidRuntime::startVm()]
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
//唉,大部分都是设置java虚拟机的启动参数。不过有几个参数比较重要。
//checkjni,可能没使用过jni的一辈子都不能体会
//说白了,就是我们在C++层调用jni函数的时候,会对参数或者什么的进行检查
//要是不合法的话,直接把虚拟机exit!第一个影响速度,第二个是影响程序。
//这个只作为开发时候使用。
property_get("dalvik.vm.checkjni", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
checkJni = true;
} else if (strcmp(propBuf, "false") != 0) {
/* property is neither true nor false; fall back on kernel parameter */
property_get("ro.kernel.android.checkjni", propBuf, "");
if (propBuf[0] == '1') {
checkJni = true;
}
}
//设置虚拟机最大heapsize,才给16M,似乎有点少,尤其是在做图片操作的
//随便一个几百兆的图片就会把虚拟机搞死。
strcpy(heapsizeOptsBuf, "-Xmx");
property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
opt.optionString = heapsizeOptsBuf;
mOptions.add(opt);
LOGD("CheckJNI is %s/n", checkJni ? "ON" : "OFF");
if (checkJni) {
/* extended JNI checking */
opt.optionString = "-Xcheck:jni";
mOptions.add(opt);
/* set a cap on JNI global references */
opt.optionString = "-Xjnigreflimit:2000";
mOptions.add(opt);
}
//具体dalvik虚拟机有哪些参数,可以参考Dalvik的说明
//反正调用了下面这个函数,虚拟机就按您指定的参数启动了。
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
LOGE("JNI_CreateJavaVM failed/n");
goto bail;
}
result = 0;
bail:
free(stackTraceFile);
return result;
}
OK,虚拟机起来了,看看我们在runtime.start中还要做什么
[--->void AndroidRuntime::start()]
if (startVm(&mJavaVM, &env) != 0)
...
//startReg?
if (startReg(env) < 0) {
goto bail;
}
看看去。
[--->int AndroidRuntime::startReg()]
为何不把startReg改成startRegister()。
int AndroidRuntime::startReg(JNIEnv* env)
{
//这个名字还是很清楚的,设置创建线程的函数为javaCreateThreadEtc
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
//JNI知识,自己去查JDK
env->PushLocalFrame(200);
//
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//搞笑,下面的注释为何不干掉?
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
[---->static int register_jni_procs()]
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) {//啥都没干,由传进来的参数控制..浪费我时间。
return -1;
}
}
return 0;
}
回到之前的调用,
register_jni_procs(gRegJNI, NELEM(gRegJNI), env),它的参数gRegJNI是下面这个结构
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_debug_JNITest),
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
...后面还有很多,好像是一些函数
};
随便挑一个跟进去看看。
[--->int register_android_debug_JNITest]
int register_android_debug_JNITest(JNIEnv* env)
{
return jniRegisterNativeMethods(env, "android/debug/JNITest",
gMethods, NELEM(gMethods));
}
其实就是注册一些JAVA中native函数在C++层对应的实行函数。
所以说:
如果你可以在这个地方加上你定制的东西。
好了,startReg完了,回到runtime.start。
[---->void AndroidRuntime::start]
if (startReg(env) < 0) {
goto bail;
}
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
//下面这些话,都是把c++的字符串转成JAVA的字符串
//
stringClass = env->FindClass("java/lang/String");
//构造一个String数组,元素个数为2
strArray = env->NewObjectArray(2, stringClass, NULL);
classNameStr = env->NewStringUTF(className);
env->SetObjectArrayElement(strArray, 0, classNameStr);
startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false");
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
//java应用程序不也有main函数吗?上面的就是把C++传进来的参数,变成java的参数
[
“com.android.internal.os.ZygoteInit”,
“true”
]
jclass startClass;
jmethodID startMeth;
//
startClass = env->FindClass(slashClassName);
// 下面这个JNI调用,就真正进入java层了
startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
//下面调用的就是com.android.internal.os.ZygoteInit类的main函数
//最后一个参数是true
env->CallStaticVoidMethod(startClass, startMeth, strArray);
bail:
free(slashClassName);
}
一 目的
zygote,是Android搞出来的一个东西。网上讲这个的也非常多。第一次看到这个名字我就挺郁闷,想干嘛这是?Linux下名字都取得挺通俗易懂,深得人心。zygote?不就想模仿Linux下的fork吗?个人觉得Google取名字挺怪,包括Google本身。
不管怎样,Zygote依然是Android系统的核心,zygote是受精卵的意思,可以认为是Android framework大家族的祖先!我们本节的目的是描述下zygote的来龙去脉,顺便揭露下它的短处,以后大家可以对症下药,变异一个更加优良的品种。
二 Zygote
zygote本身是一个应用层的程序,和驱动,内核模块之类的没点关系。这下大家放心点了吧?zygote的启动由linux的祖先init启动。这个在init分析中提过。这里就不说了。
zygote,ps中看到的进程名叫zygote,其最初的名字是app_process,通过直接调用pctrl把名字给改成了”zygote”。不过不影响我们分析。
zygote的代码在framework/base/cmds/app_process/App_main.cpp中。我们一步步来看。
既然是应用程序,直接看main咯。[/size]
int main(int argc, const char* const argv[])
{
//参数很重要啊,还记得init分析吗?
//恩,这几个参数就是:(一定要记住我们的情景分析方法!)
//zygote /system/bin/app_process
//-Xzygote /system/bin --zygote --start-system-server
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime;
//AppRuntime是个什么玩意儿?addVmArguments?好像和虚拟机有点关系喔
int i = runtime.addVmArguments(argc, argv);
[--->AppRuntime]
class AppRuntime : public AndroidRuntime
从AndroidRuntime中派生而来,是和dalvik交互的一个方便类,这里先不说了。
[---->main]
...
int i = runtime.addVmArguments(argc, argv);
....
if (i < argc) {
arg = argv[i++];
if (0 == strcmp("--zygote", arg)) {
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
//废话,根据我们的参数,startSystemServer=true
setArgv0(argv0, "zygote");
//改名字,不知道windows下的怎么改、linux下的可以用pctrl系统调用
set_process_name("zygote");
//start?记住我们的参数
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer);
}
} else {
return 10;
}
FT,app_main还是很简单的,但是runtime.start看起来不简单啊,传进去的那个参数
“com.android.internal.os.ZygoteInit“挺像java类的命名规则。
2.1 AppRuntime
好了,代码进入到runtime.start("com.android.internal.os.ZygoteInit",true)了。source insight直接进去看看。代码在framework/base/core/jni/AppRuntime.cpp中。
[--->void AndroidRuntime::start()]
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
LOGD("/n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<</n");
char* slashClassName = NULL;
char* cp;
JNIEnv* env;
//linux下signal的处理,没什么好说的
blockSigpipe();
//设置环境变量ANDROID_ROOT为/system
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
setenv("ANDROID_ROOT", rootDir, 1);
}
/*启动虚拟机*/
if (startVm(&mJavaVM, &env) != 0)
goto bail;
启动虚拟机,和JAVA有关系了吧?Android最重要的sdk都是java,那虚拟机这部分肯定要进去看看的。
[--->int AndroidRuntime::startVm()]
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
//唉,大部分都是设置java虚拟机的启动参数。不过有几个参数比较重要。
//checkjni,可能没使用过jni的一辈子都不能体会
//说白了,就是我们在C++层调用jni函数的时候,会对参数或者什么的进行检查
//要是不合法的话,直接把虚拟机exit!第一个影响速度,第二个是影响程序。
//这个只作为开发时候使用。
property_get("dalvik.vm.checkjni", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
checkJni = true;
} else if (strcmp(propBuf, "false") != 0) {
/* property is neither true nor false; fall back on kernel parameter */
property_get("ro.kernel.android.checkjni", propBuf, "");
if (propBuf[0] == '1') {
checkJni = true;
}
}
//设置虚拟机最大heapsize,才给16M,似乎有点少,尤其是在做图片操作的
//随便一个几百兆的图片就会把虚拟机搞死。
strcpy(heapsizeOptsBuf, "-Xmx");
property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
opt.optionString = heapsizeOptsBuf;
mOptions.add(opt);
LOGD("CheckJNI is %s/n", checkJni ? "ON" : "OFF");
if (checkJni) {
/* extended JNI checking */
opt.optionString = "-Xcheck:jni";
mOptions.add(opt);
/* set a cap on JNI global references */
opt.optionString = "-Xjnigreflimit:2000";
mOptions.add(opt);
}
//具体dalvik虚拟机有哪些参数,可以参考Dalvik的说明
//反正调用了下面这个函数,虚拟机就按您指定的参数启动了。
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
LOGE("JNI_CreateJavaVM failed/n");
goto bail;
}
result = 0;
bail:
free(stackTraceFile);
return result;
}
OK,虚拟机起来了,看看我们在runtime.start中还要做什么
[--->void AndroidRuntime::start()]
if (startVm(&mJavaVM, &env) != 0)
...
//startReg?
if (startReg(env) < 0) {
goto bail;
}
看看去。
[--->int AndroidRuntime::startReg()]
为何不把startReg改成startRegister()。
int AndroidRuntime::startReg(JNIEnv* env)
{
//这个名字还是很清楚的,设置创建线程的函数为javaCreateThreadEtc
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
//JNI知识,自己去查JDK
env->PushLocalFrame(200);
//
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
//搞笑,下面的注释为何不干掉?
//createJavaThread("fubar", quickTest, (void*) "hello");
return 0;
}
[---->static int register_jni_procs()]
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) {//啥都没干,由传进来的参数控制..浪费我时间。
return -1;
}
}
return 0;
}
回到之前的调用,
register_jni_procs(gRegJNI, NELEM(gRegJNI), env),它的参数gRegJNI是下面这个结构
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_debug_JNITest),
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_android_os_SystemClock),
REG_JNI(register_android_util_EventLog),
REG_JNI(register_android_util_Log),
...后面还有很多,好像是一些函数
};
随便挑一个跟进去看看。
[--->int register_android_debug_JNITest]
int register_android_debug_JNITest(JNIEnv* env)
{
return jniRegisterNativeMethods(env, "android/debug/JNITest",
gMethods, NELEM(gMethods));
}
其实就是注册一些JAVA中native函数在C++层对应的实行函数。
所以说:
如果你可以在这个地方加上你定制的东西。
好了,startReg完了,回到runtime.start。
[---->void AndroidRuntime::start]
if (startReg(env) < 0) {
goto bail;
}
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring startSystemServerStr;
//下面这些话,都是把c++的字符串转成JAVA的字符串
//
stringClass = env->FindClass("java/lang/String");
//构造一个String数组,元素个数为2
strArray = env->NewObjectArray(2, stringClass, NULL);
classNameStr = env->NewStringUTF(className);
env->SetObjectArrayElement(strArray, 0, classNameStr);
startSystemServerStr = env->NewStringUTF(startSystemServer ? "true" : "false");
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
//java应用程序不也有main函数吗?上面的就是把C++传进来的参数,变成java的参数
[
“com.android.internal.os.ZygoteInit”,
“true”
]
jclass startClass;
jmethodID startMeth;
//
startClass = env->FindClass(slashClassName);
// 下面这个JNI调用,就真正进入java层了
startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
//下面调用的就是com.android.internal.os.ZygoteInit类的main函数
//最后一个参数是true
env->CallStaticVoidMethod(startClass, startMeth, strArray);
bail:
free(slashClassName);
}
发表评论
-
Java中循环嵌套跳出的高效写法
2014-04-24 19:31 3083(下面写的这些并不是Jdk的新特性,也不是Java某个版本提供 ... -
Android各版本新增功能一览(转)
2013-12-05 20:43 1643Android3.0新增功能:主要增加全息主题 ... -
NotificationManager和Notification的使用总结(转)
2013-11-26 12:51 581这几天一直在修改twig ... -
Android应用程序资源的编译和打包过程分析 (转自老罗的博客)
2013-11-13 10:57 15465我们知道,在一个APK文件中,除了有代码文件之外,还 ... -
Proguard 源码分析 (七) 混淆
2013-11-10 21:19 1765本章我们讲Proguard非常重要的一个步骤:混淆Obfu ... -
Proguard源码分析(六)前文总结
2013-11-05 14:40 1033目前,我们读了Proguard的 ... -
Proguard源码分析(五) ConfigurationParser.keep参数
2013-10-31 14:43 3888本章节我们绕回来讲Keep参数,也就是Configurat ... -
Proguard源码分析(四) 压缩
2013-10-30 10:59 1071上一次我们讲了seed文件,这次我们说压缩,对应的输出文件是 ... -
Proguard源码分析(三)Seed文件
2013-10-29 12:45 1479Seed文件就是保持住的类文件,直白一点就是不被混淆的文件, ... -
Proguard源码分析(二)输出文件
2013-10-28 10:28 870ProGuard outputs thefollowing ... -
Android 2.2.2到Android 4.2.2源码下载地址(转)
2013-10-28 10:13 950Android 2.2.2到Android 4.2.2源码下 ... -
代码混淆器Proguard源码分析(一) 读取
2013-10-22 19:40 2261Proguard是Android中经常用的混淆工具,当然你也 ... -
Android内存之VSS/RSS/PSS/USS
2013-09-25 14:07 655Terms VSS - Vi ... -
chrome开源工程(转)
2013-09-13 10:42 1276在chrome地址栏输入about:credits就可以看 ... -
dex文件结构(转)
2013-09-03 14:10 970Dex文件和Dalvik虚拟机 在Android系统中 ... -
android clipPath切割画布
2013-08-29 12:00 6176(转自:http://wallage.blog.163.co ... -
Android WebView控件
2013-06-06 11:46 2209android.webkit库聚合了webkit内核的浏览器 ... -
dumpsys命令~(非常有用~)
2013-04-03 12:02 0dumpsys是系统中重要的函数,我们来看看它如何使用,都能 ... -
内存监控命令~
2013-04-03 00:30 0meminfo 命令:cat /proc/meminfo ... -
adb常用命令
2013-04-03 00:17 1051Android 调试桥(adb)是多种用途的工具,该工具可以 ...
相关推荐
Android Zygote启动流程源码解析
Android启动,第二大阶段,Zygote启动。 紧接上一篇《 Android启动-init介绍》Linux内核启动之后,执行第一个进程 Init,init会启动本地服务,创建Zygote等。 这里我们就来研究一下Zygote启动过程。
模拟Android系统Zygote启动流程
( Android Zygote解析
Android zygote服务/SystemServer启动流程/Activity创建,本文档继承Android init的分析,继续往下分析Zygote进程、SystemServer进程的创建、Activity的建立
主要介绍了详细分析Android中实现Zygote的源码,包括底层的C/C++代码以及Java代码部分入口,需要的朋友可以参考下
zygote启动过程zygote启动过程zygote启动过程zygote启动过程zygote启动过程
Android系统进程Zygote启动过程的源代码分析.pdf
Zygote在Android系统扮演着不可或缺的角色,Android系统的启动首先需要Zygote参与,比如启动SystemService , 还有一个就是孵化应用的进程,比如我们创建一个Activity也是需要Zygote参与. Zygote 启动分为两个部分: 1....
Android核心分析(07)----Service深入分析 Android核心分析(08)----Android 启动过程详解 Android核心分析(09)----Zygote Service Android核心分析(10)----Android GWES之基本原理篇 Android核心分析(11)--...
核心分析之七 ----- Service 深入分析 核心分析之八 ----- Android 启动过程详解 核心分析之九 ----- Zygote Service 核心分析之十 ----- Android GWES之基本原理篇 核心分析之十一 ----- Android GWES之消息系统 ...
1.初探Android 2.Android开发环境搭建与编译 3.Android编译过程分析 4.android.mk初识 5.Android.mk学习1 6.Android.mk学习2 7.Android.mk学习3 8.Android启动课程大纲 9.Android启动模式 10.init启动分析 11.走入...
NULL 博文链接:https://yishizhu.iteye.com/blog/843632
《深入理解android:卷1》是一本以情景方式对android的源代码进行深入分析的书。内容广泛,以对framework层的分析为主,兼顾native层和application层;分析深入,每一部分源代 码的分析都力求透彻;针对性强,...
Android核心分析(07)----Service深入分析 Android核心分析(08)----Android 启动过程详解 Android核心分析(09)----Zygote Service Android核心分析(10)----Android GWES之基本原理篇 Android核心分析(11)--...
ptrace注入与zygote区别和联系.V2EEptrace注入与zygote区别和联系.V2EE
移植Android以及如何开发适合各种机器的应用程序,分析Android框架所需的基础知识,JNI(Java Native Interface)与Binder基础知识,Zygote、Service Manager、Service Server等Android核心组件,Android服务框架的...
《深入理解Android:卷I》是一本以情景方式对Android的源代码进行深入分析的书。内容广泛,以对Framework层的分析为主,兼顾Native层和Application层;分析深入,每一部分源代码的分析都力求透彻;针对性强,注重实际...