日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 开发art,Android应用开发之Android 系统启动原理(art 虚拟机)

發(fā)布時間:2024/9/27 Android 83 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 开发art,Android应用开发之Android 系统启动原理(art 虚拟机) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文將帶你了解Android應(yīng)用開發(fā)之Android 系統(tǒng)啟動原理(art 虛擬機(jī)),希望本文對大家學(xué)Android有所幫助。

Android ? 系統(tǒng)啟動原理(art 虛擬機(jī))

一、虛擬機(jī)的啟動

Android 是一個 Linux 的虛擬機(jī),當(dāng)虛擬機(jī)啟動的時候,會執(zhí)行手機(jī)根目錄下的 init.rc(實(shí)際上就是 .sh 文件) 這個可執(zhí)行文件。

在 init.rc 中,有一行 on init 執(zhí)行命令。這是調(diào)用 init.rc 同級文件 init ,init 是所有安卓手機(jī)的入口執(zhí)行文件,無法打開查看,是亂碼。

xpose 的強(qiáng)大功能,就是對 init 進(jìn)行 ? hook,然后修改。但是替換 init 這個文件是需要 root 權(quán)限的,所以使用 xpose 這個框架,是需要進(jìn)行 root 的。

1.init 源碼

inti 文件的源碼是在 \system\core\init 這個文件夾下,會把里面所有的東西編譯成 init 這個可執(zhí)行文件,各個手機(jī)廠商會對這塊文件進(jìn)行修改。

init 的唯一入口是改文件夾下的 init.cpp 這個文件,里面有一個 main 函數(shù),處理環(huán)境變量,開啟服務(wù),渲染等。

main 部分代碼:

?1234567891011121314// If we're in the kernel ? domain, re-exec init to transition to the init domain now// that the SELinux ? policy has been loaded.if (is_first_stage) {????if ? (restorecon("/init") == -1) {????????ERROR("restorecon ? failed: %s\n", ? strerror(errno));????????security_failure();????}????char* ? path = argv[0];????char* args[] = { path, ? const_cast("--second-stage"), nullptr ? };????if (execv(path, args) == -1) ? {????????ERROR("execv(\"%s\") ? failed: %s\n", path, strerror(errno));????????security_failure();????}}

代碼中的 path 是指系統(tǒng)定義好的一些環(huán)境變量,這些路徑是 ? \frameworks\base\cmds 下的所有東西。

所以在這里是判斷是否是第一次啟動,如果是第一次啟動,則會執(zhí)行 \frameworks\base\cmds 下所有的可執(zhí)行文件,包括開啟虛擬機(jī)的文件 app_process。

2.app_process 源碼

\frameworks\base\cmds\app_process 下有個 app_main.cpp 文件,里面就是 app_process 源碼。

app_process 部分代碼:

?12345678910if (zygote) ? {????runtime.start("com.android.internal.os.ZygoteInit", ? args, zygote);} else if (className) ? {????runtime.start("com.android.internal.os.RuntimeInit", ? args, zygote);} else {????fprintf(stderr, "Error: no ? class name or --zygote ? supplied.\n");????app_usage();????LOG_ALWAYS_FATAL("app_process: ? no class name or --zygote supplied.");????return ? 10;}

在 app_main 里面的 main 方法最后,調(diào)用了 runtime.start(“com.android.internal.os.ZygoteInit”, args, ? zygote);

點(diǎn)擊查看 run 是第一 AppRuntime。

所以 app_process 調(diào)用了 ? com.android.internal.os.ZygoteInit 這個類,這是第一個被調(diào)用的 java 類。對應(yīng)源碼位置是 \frameworks\base\core\java\com\android\internal\os

3.AndroidRuntime

AppRuntime 繼承于 AndroidRuntime,AndroidRuntime 位于\frameworks\base\core\jni。

start 部分代碼:

?123if (startVm(&mJavaVM, &env, zygote) ? != 0) {????return;}

在 AndroidRuntime 的 start 方法中,調(diào)用了 startVm,這個方法,這個方法才是真正的去開啟虛擬機(jī)。手機(jī)啟動的時候只是開啟 Linux 系統(tǒng),當(dāng)執(zhí)行到這里的時候,Linux 系統(tǒng)開啟安卓運(yùn)行的虛擬機(jī)。

startVm 部分代碼:

?1234567891011/*?* Initialize the ? VM.?*?* The JavaVM* is essentially per-process, and the JNIEnv* is ? per-thread.?* If this call succeeds, the VM is ready, and we can start ? issuing?* JNI calls.?*/if (JNI_CreateJavaVM(pJavaVM, pEnv, ? &initArgs) < 0) {????ALOGE("JNI_CreateJavaVM ? failed\n");????return -1;}

在 startVm 末尾調(diào)用 JNI_CreateJavaVM,去創(chuàng)建一個虛擬機(jī)。

4.JNI_CreateJavaVM

JNI_CreateJavaVM 方法位于 \art\runtime\jni_internal.cc 文件中。

JNI_CreateJavaVM :

?1234567891011121314151617181920212223242526272829// ? JNI Invocation interface.?extern "C" jint ? JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) ? {??const JavaVMInitArgs* args = ? static_cast(vm_args);??if ? (IsBadJniVersion(args->version)) {????LOG(ERROR) ? << "Bad JNI version passed to CreateJavaVM: " << ? args->version;????return ? JNI_EVERSION;??}??Runtime::Options ? options;??for (int i = 0; i < args->nOptions; ++i) ? {????JavaVMOption* option = ? &args->options[i];????options.push_back(std::make_pair(std::string(option->optionString), ? option->extraInfo));??}??bool ignore_unrecognized = ? args->ignoreUnrecognized;??if (!Runtime::Create(options, ? ignore_unrecognized)) {????return ? JNI_ERR;??}??Runtime* runtime = Runtime::Current();??bool ? started = runtime->Start();??if (!started) ? {????delete ? Thread::Current()->GetJniEnv();????delete ? runtime->GetJavaVM();????LOG(WARNING) << "CreateJavaVM ? failed";????return ? JNI_ERR;??}??*p_env = ? Thread::Current()->GetJniEnv();??*p_vm = ? runtime->GetJavaVM();??return JNI_OK;}

其中最主要的最后兩行代碼,實(shí)例化了 ? p_env 和 p_vm ,p_env 就是我們編寫 jni 方法的第一個參數(shù) JNIEnv *env ,p_vm 就是虛擬機(jī)。

//JNIEnv *env 實(shí)例化

*p_env = Thread::Current()->GetJniEnv();

//實(shí)例化虛擬機(jī)的地方

*p_vm = runtime->GetJavaVM();

注:虛擬機(jī)在 Linux 就是一個結(jié)構(gòu)體的方式保存著。

5.p_env

GetJniEnv() 這個函數(shù)定義在文件 \art\runtime 下的 thread.h 中。

* thread.h *

?1234567// Every thread may have an associated ? JNI environmentJNIEnvExt* jni_env_;?// JNI methodsJNIEnvExt* GetJniEnv() ? const {??return jni_env_;}

JNI 方法的第一個參數(shù)是 JNIEnv,JNIEnv ? 是一個接口, JNIEnvExt 是 JNIEnv子類。

二、加載 java 文件

在 ? \frameworks\base\core\jni\AndroidRuntime 中繼續(xù)往下,會發(fā)現(xiàn)加載 java 類,實(shí)際上是調(diào)用 env->FindClass(slashClassName) 進(jìn)行加載的。(java 中 雙親委托機(jī)制 ClassLoader 進(jìn)行加載 java 文件,最底層的實(shí)現(xiàn)也是使用 FindClass 這個方法)

1.FindClass

FindClass 是在 libnativehelper\include\nativehelper\jni.h 中,

jni.h 下 FindClass :

jclass FindClass(const char* name){ return ? functions->FindClass(this, name); }

這里的 functions 是 JNINativeInterface,最終調(diào)用的是 \art\runtime\jni_internal.cc ? 下的 FindClass 。

\jni_internal.cc 下 FindClass:

static jclass ? FindClass(JNIEnv* env, const char* name) ? {??CHECK_NON_NULL_ARGUMENT(name);??Runtime* runtime = ? Runtime::Current();??ClassLinker* class_linker = ? runtime->GetClassLinker();??std::string ? descriptor(NormalizeJniClassDescriptor(name));??ScopedObjectAccess ? soa(env);??mirror::Class* c = nullptr;??//判斷虛擬機(jī)是否開啟??if ? (runtime->IsStarted()) {????StackHandleScope<1>? hs(soa.Self());????Handleclass_loader(hs.NewHandle(GetClassLoader(soa)));????c = ? class_linker->FindClass(soa.Self(), descriptor.c_str(), ? class_loader);??} else {????//還沒開啟虛擬機(jī),即加載的是系統(tǒng)的類????c ? = class_linker->FindSystemClass(soa.Self(), ? descriptor.c_str());??}??return ? soa.AddLocalReference(c);}

最終程序調(diào)用到 class_linker 的 FindClass 方法進(jìn)行加載類。

2. class_linker 的 FindClass

class_linker 所在目錄 \art\runtime 下有一個 class_linker.cc 文件,找到里面的 FindClass 方法。

FindClass 部分代碼:

if (pair.second != nullptr) {??return ? DefineClass(self,?????????????????????descriptor,?????????????????????hash,?????????????????????ScopedNullHandle(),?????????????????????*pair.first,?????????????????????*pair.second);}

在這邊調(diào)用了 DefineClass。

DefineClass 部分代碼:

// Add the newly loaded class to the loaded ? classes table.mirror::Class* existing = InsertClass(descriptor, klass.Get(), ? hash);if (existing != nullptr) {??// We failed to insert because we ? raced with another thread. Calling EnsureResolved may cause??// ? this thread to block.??return EnsureResolved(self, descriptor, ? existing);}?// Load the fields and other things after we are inserted in ? the table. This is so that we don't// end up allocating unfree-able linear ? alloc resources and then lose the race condition. The// other reason is that ? the field roots are only visited from the class table. So we need to be// ? inserted before we allocate / fill in these fields.LoadClass(self, dex_file, ? dex_class_def, klass);

這是調(diào)用了兩個比較重要的方法, ? InsertClass 和 LoadClass。

InsertClass(descriptor, klass.Get(), hash); 有一個參數(shù)是 hash,這樣會把類進(jìn)行緩存,在 DefineClass 執(zhí)行 InsertClass 之前,會先進(jìn)行這個判斷,如果已經(jīng)加載的就不再進(jìn)行加載。

LoadClass(self, dex_file, dex_class_def, klass); ? 是真正的去進(jìn)行加載 Class。

LoadClass:

void ? ClassLinker::LoadClass(Thread* ? self,????????????????????????????const ? DexFile& ? dex_file,????????????????????????????const ? DexFile::ClassDef& dex_class_def,????????????????????????????Handleklass) {??const uint8_t* class_data = ? dex_file.GetClassData(dex_class_def);??if (class_data == nullptr) ? {????return;? // no fields or methods - for example ? a marker interface??}??bool has_oat_class = ? false;??if (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler()) ? {????OatFile::OatClass oat_class = FindOatClass(dex_file, ? klass->GetDexClassDefIndex(),???????????????????????????????????????????????&has_oat_class);????if ? (has_oat_class) {??????LoadClassMembers(self, ? dex_file, class_data, klass, ? &oat_class);????}??}??if ? (!has_oat_class) {????LoadClassMembers(self, dex_file, ? class_data, klass, nullptr);??}}

最開始是通過 DexFile 去獲取到 ClassData。因?yàn)樵陬愡€沒加載的時候,class 是以 dex格式 存在在 磁盤 文件下,這時候需要先把 dex 轉(zhuǎn)為 ? class,再把 class 加載到內(nèi)存中。

然后通過 LoadClassMembers ? 進(jìn)行加載類的信息,分配內(nèi)存。LoadClassMembers ? 中分別對 ArtField 和 ArtMethod 進(jìn)行初始化。

本文由職坐標(biāo)整理并發(fā)布,希望對同學(xué)們有所幫助。了解更多詳情請關(guān)注職坐標(biāo)移動開發(fā)之Android頻道!

總結(jié)

以上是生活随笔為你收集整理的android 开发art,Android应用开发之Android 系统启动原理(art 虚拟机)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美成人综合网站 | 欧美视频xxx| 樱花电影最新免费观看国语版 | 日本高清网色 | 天天燥日日燥 | 精品久久久久一区 | 久久精品人人做人人爽 | 久久久久久久久久久久久久久久久久 | 日韩美女免费视频 | 国产精品88久久久久久妇女 | 日本精品一区在线观看 | 三级全黄的视频 | www.日本黄| 精品国产高清在线观看 | 调教丰满的已婚少妇在线观看 | 一区二区三区在线播放视频 | 国产乡下妇女三片 | 欧美久久久久久 | 国产一区二区三区色淫影院 | 特大黑人巨交吊性xx | 午夜精品一区二区三区在线观看 | 天天干天天天天 | 亚洲理论在线观看 | 3d成人动漫在线观看 | 欧美亚洲精品一区 | 可以看的毛片 | 欧美精品手机在线 | 欧美激情aaa | 极品探花在线 | 亚洲视频在线观看网站 | 外国电影免费观看高清完整版 | 在线成人观看 | www.香蕉.com | 国产经典一区二区三区 | 超碰99在线 | 欧美一级大片在线观看 | 丝袜熟女一区二区 | 哺乳援交吃奶在线播放 | 一区二区不卡免费视频 | 国产精品国产三级国产aⅴ9色 | 樱花草av| 午夜羞羞影院 | 96日本xxxxxⅹxxx70| 香港日本韩国三级网站 | 四虎国产精品永久在线国在线 | 91天堂在线视频 | 成人免费在线视频观看 | 精品久久久久久久久久久 | 久久久欧美 | 亚洲综合免费观看高清完整版 | 日本美女毛片 | 久久精品操 | 久久久久免费精品 | 日本少妇一区二区 | 国产精品无码在线 | 久久久久国产一区二区三区潘金莲 | 国产精九九网站漫画 | 亚洲日本一区二区 | 麻豆精品a∨在线观看 | 成人欧美一级特黄 | 中文字幕在线观看精品 | 久久精品国产久精国产 | 亚洲精品视屏 | 最近中文字幕免费mv视频7 | 国产午夜精品久久 | 干操网| 欧美18一20男同69gay | 天天综合网国产 | www.xxxxx日本 | 亚州欧美日韩 | 亚洲小视频在线播放 | 国产又粗又硬 | 日本高清三区 | 美女久久久久久 | 欧美日韩一区二区三区免费 | 又黄又爽视频 | 国产专区一区二区 | 日本少妇一级片 | 男女激情在线观看 | 永久在线| 日韩一区二区三区网站 | 国产二区电影 | 一区二区三区视频免费观看 | 国产裸体永久免费无遮挡 | 亚洲熟乱 | 91呦呦 | 麻豆视频在线观看免费 | 韩国三级做爰高潮 | 国产精品国产a级 | 神马午夜51 | 中文字幕+乱码+中文字幕一区 | 夜夜躁很很躁日日躁麻豆 | 日韩av一区二区三区四区 | 色婷婷综合在线 | 综合网激情 | 色呦呦网| 色婷婷国产精品视频 | 中文在线免费观看 | 午夜激情视频 |