--- title: 'Android Runtime、Thread' disqus: kyleAlien --- Android Runtime === ## OverView of Content [TOC] ## Runtime 是什麼 :::success * [**Runtime 是啥**](https://stackoverflow.com/questions/3900549/what-is-runtime) ? **++簡單來說就是支持程式運行的基礎 Library,Runtime 與語言綁定++** ```shell= 1. C Runtime: 綁定 C standard library 2. Java Runtime: 綁定 Java Virtual Machine (包括 `.jar` 包) 3. Android Runtime: 綁定 Dalvik... 等等必要工具 ``` ::: ### Android Runtime 概述 * 啟動 Android Runtime,**綁定如下** 1. **Dalvik VM**: Android Java VM,**其功能是解析 Dex 檔案,每個進程皆有一個虛擬機** :::info * **虛擬機功能、JIN** ? 1. 虛擬機主要是在解釋 Dex 格式的 ByteCode,並將這些 ByteCode 翻譯成裝置能懂得二進制程式 2. JIN,全名是 `Just In Time` 它的功能是把程式預先轉為二進制,從而大大提高了效能 (一般來說傳統 C、C++ 這種靜態語言才跑得比較快,但 JIN 讓 Java 跑得更快,甚至可能超過 C、C++ 程式) ::: 2. **Android Java Library**: 大部份來自於 Apache Hamony,開源的 Java API,Eg. `java.lang`、`java.util`、`java.net` 3. **JNI**: C、C++ 與 Java 相互調用的接口 4. **Libc**: Android 使用的 libc 是 `bionic` ## Runtime 啟動 * **Runtime 啟動時機**: Android runtime 是透過 init 進程 -> 觸發 Zygote ([**app_main**](https://android.googlesource.com/platform/frameworks/base/+/master/cmds/app_process/app_main.cpp)#main)進程啟動 -> 在 Zygote 創建的過程中啟動 ```cpp= // /cmds/app_process/app_main.cpp int main(int argc, char* const argv[]) { ... // argv[0] 是啟動名稱,eg. zygote AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); int i; ...依照分析的參數啟動 Android Runtime if (zygote) { // runtime 是 AndroidRuntime 對象 // 啟動 ZygoteInit 類 runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { ... } } ``` > ![](https://i.imgur.com/LwCicNC.png) ### 啟動虛擬機 - AndroidRuntime#start * Zygote 進程對 AndroidRuntime **傳入 class 路徑** 後,ZygoteInit 就會啟動在 Java 虛擬機上(透過 [**AndroidRuntime**](https://android.googlesource.com/platform/frameworks/base/+/master/core/jni/AndroidRuntime.cpp) 的 start 函數),其中較為重要的函數如下 | 函數名 | 功能 | | -------- | -------- | | startVm | 啟動 Java 虛擬機 | | startReg | 完成 Java 虛擬機的 JNI 註冊 | ```cpp= // /core/jni/AndroidRuntime.cpp void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ... JNIEnv* env; // 啟動虛擬機 @startVm 繼續往下分析 if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) { return; } // 啟動後的回調 onVmCreated(env); /* * Register android functions. */ // @ startReg if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } ... 省略部分 } int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote) { ... 省略虛擬機參數設定 /* * 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. */ // 對 JNI_CreateJavaVM 繼續往下分析 if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { ALOGE("JNI_CreateJavaVM failed\n"); return -1; } return 0; } ``` > ![](https://i.imgur.com/4dhSm4Y.png) ## 啟動 Java 虛擬機 - startVm 現在來分析 startVm 函數 ```cpp= // /core/jni/AndroidRuntime.cpp void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ... JNIEnv* env; // 啟動虛擬機 @startVm 繼續往下分析 if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) { return; } ... 省略部分 } int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote) { ... 省略虛擬機參數設定 /* * 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. */ // 對 JNI_CreateJavaVM 繼續往下分析 if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { ALOGE("JNI_CreateJavaVM failed\n"); return -1; } return 0; } ``` ### JNI 創建虛擬機 - [JNI_CreateJavaVM](https://android.googlesource.com/platform/art/+/refs/heads/master/runtime/jni/java_vm_ext.cc) * Native 層透過 JNI 調用 Java 函數來創建虛擬機實例 ```cpp= // /runtime/java_vm_ext.cc extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) { ScopedTrace trace(__FUNCTION__); const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args); if (JavaVMExt::IsBadJniVersion(args->version)) { LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version; return JNI_EVERSION; } // 設定 runtime 參數 RuntimeOptions 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; // 透過 Runtime 靜態方法 Create 創建 !!! if (!Runtime::Create(options, ignore_unrecognized)) { return JNI_ERR; } ... 省略部分 android::InitializeNativeLoader(); // 取得當前 runtime Runtime* runtime = Runtime::Current(); // 啟動 runtime 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; } ``` > ![](https://i.imgur.com/T5M09mF.png) ### 創建 [Runtime](https://android.googlesource.com/platform/art/+/master/runtime/runtime.cc) 實例 * 靜態單例創建 [**Runtime**](https://android.googlesource.com/platform/art/+/master/runtime/runtime.cc) 實例,而 Runtime 單例是 ++進程單例++ ```cpp= // /runtime/runtime.cc Runtime* Runtime::instance_ = nullptr; bool Runtime::Create(const RuntimeOptions& raw_options, bool ignore_unrecognized) { RuntimeArgumentMap runtime_options; // @ 分析 Create return ParseOptions(raw_options, ignore_unrecognized, &runtime_options) && Create(std::move(runtime_options)); } bool Runtime::Create(RuntimeArgumentMap&& runtime_options) { // TODO: acquire a static mutex on Runtime to avoid racing. if (Runtime::instance_ != nullptr) { return false; } // 創建 Runtime 實例 instance_ = new Runtime; Locks::SetClientCallback(IsSafeToCallAbort); // @ 分析 Init if (!instance_->Init(std::move(runtime_options))) { instance_ = nullptr; return false; } return true; } ``` > ![](https://i.imgur.com/5KrgJgc.png) ### 初始化 [Runtime#Init](https://android.googlesource.com/platform/art/+/master/runtime/runtime.cc#1344) - 創建 JVM、堆棧、類連結 * Runtime 會初始化創建 `堆棧`、創建 JVM 實例 1. **gc::Heap** 創建 JVM 使用的 **堆棧空間** ```cpp= // /runtime/runtime.cc bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { ... 省略部分 // 創建堆管理對象 (也就是 Heap) heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize), runtime_options.GetOrDefault(Opt::HeapGrowthLimit), runtime_options.GetOrDefault(Opt::HeapMinFree), runtime_options.GetOrDefault(Opt::HeapMaxFree), runtime_options.GetOrDefault(Opt::HeapTargetUtilization), foreground_heap_growth_multiplier, runtime_options.GetOrDefault(Opt::StopForNativeAllocs), runtime_options.GetOrDefault(Opt::MemoryMaximumSize), runtime_options.GetOrDefault(Opt::NonMovingSpaceCapacity), GetBootClassPath(), GetBootClassPathLocations(), GetBootClassPathFds(), GetBootClassPathImageFds(), GetBootClassPathVdexFds(), GetBootClassPathOatFds(), image_locations_, instruction_set_, // Override the collector type to CC if the read barrier config. kUseReadBarrier ? gc::kCollectorTypeCC : xgc_option.collector_type_, kUseReadBarrier ? BackgroundGcOption(gc::kCollectorTypeCCBackground) : runtime_options.GetOrDefault(Opt::BackgroundGc), runtime_options.GetOrDefault(Opt::LargeObjectSpace), runtime_options.GetOrDefault(Opt::LargeObjectThreshold), runtime_options.GetOrDefault(Opt::ParallelGCThreads), runtime_options.GetOrDefault(Opt::ConcGCThreads), runtime_options.Exists(Opt::LowMemoryMode), runtime_options.GetOrDefault(Opt::LongPauseLogThreshold), runtime_options.GetOrDefault(Opt::LongGCLogThreshold), runtime_options.Exists(Opt::IgnoreMaxFootprint), runtime_options.GetOrDefault(Opt::AlwaysLogExplicitGcs), runtime_options.GetOrDefault(Opt::UseTLAB), xgc_option.verify_pre_gc_heap_, xgc_option.verify_pre_sweeping_heap_, xgc_option.verify_post_gc_heap_, xgc_option.verify_pre_gc_rosalloc_, xgc_option.verify_pre_sweeping_rosalloc_, xgc_option.verify_post_gc_rosalloc_, xgc_option.gcstress_, xgc_option.measure_, runtime_options.GetOrDefault(Opt::EnableHSpaceCompactForOOM), use_generational_cc, runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs), runtime_options.Exists(Opt::DumpRegionInfoBeforeGC), runtime_options.Exists(Opt::DumpRegionInfoAfterGC)); ... 省略部分 } ``` 2. **JavaVMExt::Create** 創建 JVM 實例 ```cpp= // /runtime/runtime.cc bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { ... 省略部分 std::string error_msg; // 創建 JVM 虛擬機 java_vm_ = JavaVMExt::Create(this, runtime_options, &error_msg); if (java_vm_.get() == nullptr) { LOG(ERROR) << "Could not initialize JavaVMExt: " << error_msg; return false; } // Add the JniEnv handler. // TODO Refactor this stuff. java_vm_->AddEnvironmentHook(JNIEnvExt::GetEnvHandler); ...省略部分 } ``` 3. **Thread::Attach** 創建 main Thread ```cpp= // /runtime/runtime.cc #include "thread.h" bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { ... 省略部分 // 開始線程 Thread::Startup(); // 創建主線程,並把該線程取為 main Thread* self = Thread::Attach("main", false, nullptr, false); CHECK_EQ(self->GetThreadId(), ThreadList::kMainThreadId); CHECK(self != nullptr); self->SetIsRuntimeThread(IsAotCompiler()); // Set us to runnable so tools using a runtime can allocate and GC by default self->TransitionFromSuspendedToRunnable(); // Now we're attached, we can take the heap locks and validate the heap. GetHeap()->EnableObjectValidation(); CHECK_GE(GetHeap()->GetContinuousSpaces().size(), 1U); ...省略部分 } ``` 4. **ClassLinker** 創建類連結器,並將它初始化 ```cpp= // /runtime/runtime.cc bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { ... 省略部分 // 創建類連結器 if (UNLIKELY(IsAotCompiler())) { class_linker_ = new AotClassLinker(intern_table_); } else { class_linker_ = new ClassLinker( intern_table_, runtime_options.GetOrDefault(Opt::FastClassNotFoundException)); } if (GetHeap()->HasBootImageSpace()) { // 初始化類連結器 bool result = class_linker_->InitFromBootImage(&error_msg); if (!result) { LOG(ERROR) << "Could not initialize from image: " << error_msg; return false; } if (kIsDebugBuild) { for (auto image_space : GetHeap()->GetBootImageSpaces()) { image_space->VerifyImageAllocations(); } } ...省略部分 VLOG(startup) << "Runtime::Init exiting"; return true; } ``` > ![](https://i.imgur.com/mp8YORJ.png) ### 創建 main Thread * main Thread 會在虛擬機創建時 (Init 時) 被創建出來 ```cpp= // /runtime/runtime.cc #include "thread.h" bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { ... 省略部分 // 開始線程 Thread::Startup(); // 創建主線程,並把該線程取為 main Thread* self = Thread::Attach("main", false, nullptr, false); CHECK_EQ(self->GetThreadId(), ThreadList::kMainThreadId); CHECK(self != nullptr); self->SetIsRuntimeThread(IsAotCompiler()); // Set us to runnable so tools using a runtime can allocate and GC by default self->TransitionFromSuspendedToRunnable(); // Now we're attached, we can take the heap locks and validate the heap. GetHeap()->EnableObjectValidation(); CHECK_GE(GetHeap()->GetContinuousSpaces().size(), 1U); ...省略部分 } ``` * Thread 是透過 C++ `new` 創建的空間 ```cpp= template <typename PeerAction> Thread* Thread::Attach(const char* thread_name, bool as_daemon, PeerAction peer_action) { // 判斷 Runtime 實例 Runtime* runtime = Runtime::Current(); if (runtime == nullptr) { ... 省略錯誤 log return nullptr; } Thread* self; { MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_); if (runtime->IsShuttingDownLocked()) { ... 省略錯誤 log return nullptr; } else { Runtime::Current()->StartThreadBirth(); // ++ 創建新 Thread++ self = new Thread(as_daemon); // 初始化 Thread bool init_success = self->Init(runtime->GetThreadList(), runtime->GetJavaVM()); Runtime::Current()->EndThreadBirth(); // 若初始化失敗則 delete 記憶體空間 if (!init_success) { delete self; return nullptr; } } } self->InitStringEntryPoints(); CHECK_NE(self->GetState(), kRunnable); self->SetState(kNative); // Run the action that is acting on the peer. if (!peer_action(self)) { runtime->GetThreadList()->Unregister(self); // Unregister deletes self, no need to do this here. return nullptr; } ... 省略部份 { ScopedObjectAccess soa(self); runtime->GetRuntimeCallbacks()->ThreadStart(self); } return self; } ``` ### 虛擬機啟動時序圖 * 虛擬機啟動時序圖 - 調用到 Runtime 前 > ![](https://i.imgur.com/aRjrNOQ.png) * Java 虛擬機啟動時序圖 - 調用到 Runtime 後 > ![](https://i.imgur.com/pHTVzrT.png) ## onVmCreated - 創建全域連結 ```cpp= // /core/jni/AndroidRuntime.cpp void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ... JNIEnv* env; // 啟動虛擬機 @startVm 繼續往下分析 if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) { return; } // 啟動後的回調,創建全域連結 onVmCreated(env); ... 省略部分 } ``` ### 創建 class 的全域連結 * 創建 class 的全域連結 (**NewGlobalRef**),如果 Zygote 則不會做其他事情 ```cpp= // /core/jni/AndroidRuntime.cpp class AppRuntime : public AndroidRuntime { public: AppRuntime(char* argBlockStart, const size_t argBlockLength) : AndroidRuntime(argBlockStart, argBlockLength) , mClass(NULL) { } void setClassNameAndArgs(const String8& className, int argc, char * const *argv) { mClassName = className; for (int i = 0; i < argc; ++i) { mArgs.add(String8(argv[i])); } } virtual void onVmCreated(JNIEnv* env) { // Zygote 進程會傳空進來 if (mClassName.isEmpty()) { return; // Zygote. Nothing to do here. } char* slashClassName = toSlashClassName(mClassName.string()); mClass = env->FindClass(slashClassName); if (mClass == NULL) { ALOGE("ERROR: could not find class '%s'\n", mClassName.string()); } free(slashClassName); // 創建全域連結 mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass)); } ... 省略部分函數 String8 mClassName; Vector<String8> mArgs; jclass mClass; }; ``` ## AndroidRuntime - startReg 啟動 Runtime & JVM 後,**透過 `startReg()` 註冊 ++JVM 全部的 Native 方法++** ```cpp= // /core/jni/AndroidRuntime.cpp void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ... /* * Register android functions. */ if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } ... 省略部分 } int AndroidRuntime::startReg(JNIEnv* env) { ... androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc); ... env->PushLocalFrame(200); // @ 追蹤 register_jni_procs 函數 if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { env->PopLocalFrame(NULL); return -1; } env->PopLocalFrame(NULL); //createJavaThread("fubar", quickTest, (void*) "hello"); return 0; } ``` ### JVM 的 JNI 註冊 - register_jni_procs * `register_jni_procs` 函數會循環調用 **gRegJNI 數組** 的成員所對應的方法 1. register_jni_procs 函數 ```cpp= // AndroidRuntime.cpp 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) { // 判斷是否成功 ... 錯誤函數指針 log return -1; } } return 0; } ``` 2. gRegJNI 數組:內全部都是要註冊的函數指針,回傳小於 0 則代表註冊失敗 ```cpp= // AndroidRuntime.cpp #ifdef NDEBUG #define REG_JNI(name) { name } struct RegJNIRec { // 指針函數 int (*mProc)(JNIEnv*); } // REG_JNI 是一個宏 static const RegJNIRec gRegJNI[] = { // 其成員全部都是函數指針 // 拿 register_com_android_internal_os_RuntimeInit 舉個例子 REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit), REG_JNI(register_android_os_SystemClock), REG_JNI(register_android_util_CharsetUtils), REG_JNI(register_android_util_EventLog), REG_JNI(register_android_util_Log), REG_JNI(register_android_util_MemoryIntArray), REG_JNI(register_android_app_admin_SecurityLog), REG_JNI(register_android_content_AssetManager), ... 省略部份 } // 註冊範例 int register_com_android_internal_os_RuntimeInit(JNIEnv* env) { const JNINativeMethod methods[] = { {"nativeFinishInit", "()V", (void*)com_android_internal_os_RuntimeInit_nativeFinishInit}, {"nativeSetExitWithoutCleanup", "(Z)V", (void*)com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup}, }; return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit", methods, NELEM(methods)); } int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env) { const JNINativeMethod methods[] = { { "nativeZygoteInit", "()V", (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit }, }; return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit", methods, NELEM(methods)); } ``` ## Java Thread 類 線程是操作系統 CPU 分配資源的基礎單位,**屬於抽象範疇** 線程仍是可執行的程式,就這一點來說 Thread 與其他的類並無不同,不過 Thread 中的屬性 & 方法僅用於完成 **==線程管理== 這像任務**(開始、停止、中斷.... 這些操作) :::info * 有關 Thread 的其他操做,請看另一篇 [**Thread 使用文章**](https://hackmd.io/7Ru0TE45Tnm1LEUqx4qe-A?view) ::: ### [Thread](https://cs.android.com/android/platform/superproject/+/master:libcore/ojluni/src/main/java/java/lang/Thread.java) 內部原理 - [Runnable](https://cs.android.com/android/platform/superproject/+/master:libcore/ojluni/src/main/java/java/lang/Runnable.java) * Thread 內部實現了 Runnable 界面 ```java= // Runnable.java public interface Runnable { public abstract void run(); } // ------------------------------------------------------- // Thread.java public class Thread implements Runnable { ... 省略 } ``` * 使用方法有兩種,最後會間接調用到 run 方法 1. 繼承 Thread,並重寫 Runnable 的 run() 方法 ```java= class ThreadImpl extends Thread { @Override public void run() { // TODO: } } ``` 2. 匿名直接實現 Runnable 方法,並設定給 Thread ```java= class ThreadImpl_2 { void threadTest() { Thread t = new Thread(new Runnable() { @Override public void run() { // TODO } }); } } ``` * 分析 Thead#start 方法:start 方法會呼叫 Native nativeCreate 創建 thread ```java= // Thread.java boolean started = false; public synchronized void start() { // 已啟動,再次呼叫 start 則會拋出 IllegalThreadStateException 異常 if (started) throw new IllegalThreadStateException(); group.add(this); started = false; try { // @ 追蹤Native 方法 nativeCreate(this, stackSize, daemon); started = true; } /* 省略 finally */ } private native static void nativeCreate(Thread t, long stackSize, boolean daemon); ``` :::success * Thread 有以下幾種狀態 ```java= // /java/lang/Thread.java public enum State { /** * The thread has been created, but has never been started. */ NEW, /** * The thread may be run. */ RUNNABLE, /** * The thread is blocked and waiting for a lock. */ BLOCKED, /** * The thread is waiting. */ WAITING, /** * The thread is waiting for a specified amount of time. */ TIMED_WAITING, /** * The thread has been terminated. */ TERMINATED } ``` ::: ### Android 應用 - 使用多執行序 の 方法 * 這種 **併發** 編程技術,在 Android 中主要有三種方式可以執行,詳細的使用、分析可以點進連結去了解(寫在另外一篇文章) 1. 繼承 Thread or 實做 Runnable 方法 2. 使用 Android 提供的特殊類 * 使用 [**AsyncTask**](https://hackmd.io/ouTTernZT7uH5RBJHCCq5A) 這個類(適合 ++短期操作++) * 使用 [**Executor、ThreadPoolExecutor**](https://hackmd.io/ouTTernZT7uH5RBJHCCq5A) 這個類(適合 ++長期操作++) 3. 使用 [**IntentServer**](https://hackmd.io/qwwq4oLMTmaw2UksbpPOUg#IntentService) 這個類,它是 Server 的子類,**運作在子線程** ## Native Thread 相關知識 :::info Native Thread 就是對 pThread 做一個簡單的封裝 ::: ### [java_lang_thread](https://cs.android.com/android/platform/superproject/+/master:art/runtime/native/java_lang_Thread.cc) - nativeCreate * 在上面我們看到 Java Thread#start 方法,會呼叫 Natvie#nativeCreate 方法(JNI 類),它會對應到 [**java_lang_Thread.cc**](https://cs.android.com/android/platform/superproject/+/master:art/runtime/native/java_lang_Thread.cc)#Thread_nativeCreate 方法 | Java 方法 | JNI 方法 | | -------- | -------- | | nativeCreate | **Thread_nativeCreate** | ```java= // java_lang_Thread.cc static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size, jboolean daemon) { ... 省略部分 Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE); } ``` * [**Thread**](https://cs.android.com/android/platform/superproject/+/master:art/runtime/thread.cc)#CreateNativeThread:創建 [**Natvie thread 對象**](https://cs.android.com/android/platform/superproject/+/master:art/runtime/thread.cc),並 **將 Java thread 對象存入 Native**,再呼叫 `pthread_create` 方法 (另個小節分析) ```cpp= // thread.cc void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) { ... 省略部分 // 創建 c++ 層的 thread 對象 Thread* child_thread = new Thread(is_daemon); // 將 Java thread 對象存入 Native child_thread->tlsPtr_.jpeer = env->NewGlobalRef(java_peer); ... 省略部分 int pthread_create_result = 0; if (child_jni_env_ext.get() != nullptr) { pthread_t new_pthread; ... 省略部分 // @ 之後分析 pthread_create 方法 pthread_create_result = pthread_create(&new_pthread, &attr, Thread::CreateCallback, child_thread); CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread"); if (pthread_create_result == 0) { child_jni_env_ext.release(); // NOLINT pthreads API. return; } } ``` ### [Threads](https://cs.android.com/android/platform/superproject/+/master:system/core/libutils/Threads.cpp) run - ThreadPool 線程池 * 有另一種情況,在 Zygote 啟動時,我們在 App 啟動時 AndroidRuntime 會透過 [**ProcessState**](https://cs.android.com/android/platform/superproject/+/master:system/libhwbinder/ProcessState.cpp) 創建 ThreadPool :::success * 詳細請參考 [**啟動 Binder 線程池**](https://hackmd.io/Yw1s2x32QoqawvOsW039ZA?view#Binder-%E7%B7%9A%E7%A8%8B%E6%B1%A0) 分析 ::: ```cpp= // ProcessState.cpp void ProcessState::spawnPooledThread(bool isMain) { if (mThreadPoolStarted) { String8 name = makeBinderThreadName(); ALOGV("Spawning new pooled thread, name=%s\n", name.string()); sp<Thread> t = new PoolThread(isMain); t->run(name.string()); } } ``` * [**Thread**](https://cs.android.com/android/platform/superproject/+/master:system/core/libutils/Threads.cpp)#run 方法對於線程的創建有分為兩種 | 創建來源 | 實做方法 | | -------- | -------- | | Java | createThreadEtc | | Native | androidCreateRawThreadEtc | ```cpp= // /libutils/Threads.cpp status_t Thread::run(const char* name, int32_t priority, size_t stack) { ... 省略部份 mStatus = OK; mExitPending = false; mThread = thread_id_t(-1); // hold a strong reference on ourself mHoldSelf = this; mRunning = true; bool res; // 區分兩種創建方式 if (mCanCallJava) { // Java 創建 // @ 追蹤 createThreadEtc res = createThreadEtc(_threadLoop, this, name, priority, stack, &mThread); } else { // Native 創建 // @ 追蹤 androidCreateRawThreadEtc res = androidCreateRawThreadEtc(_threadLoop, this, name, priority, stack, &mThread); } // 創建失敗處理 if (res == false) { mStatus = UNKNOWN_ERROR; // something happened! mRunning = false; mThread = thread_id_t(-1); mHoldSelf.clear(); // "this" may have gone away after this. return UNKNOWN_ERROR; } return OK; } ``` 1. **Native Thread 創建 pThread**:**Native 層創建的 Thread 其實就是創建一個 ++pThread 對象++** ```cpp= // Threads.cpp int androidCreateRawThreadEtc(android_thread_func_t entryFunction, void *userData, const char* threadName __android_unused, int32_t threadPriority, size_t threadStackSize, android_thread_id_t *threadId) { // 創建 pthead 使用的屬性參數 pthread_attr_t attr; pthread_attr_init(&attr); .. 省略部分 errno = 0; // 創建 pthread 對象 pthread_t thread; // @ 分析 pthread_create 方法 int result = pthread_create(&thread, &attr, (android_pthread_entry)entryFunction, userData); pthread_attr_destroy(&attr); if (result != 0) { // 創建失敗 log... return 0; } // 設定 thread id if (threadId != nullptr) { *threadId = (android_thread_id_t)thread; // XXX: this is not portable } // 成功返回 1 return 1; } ``` 2. **Java Thread 創建 pThread**:從 **`Threads.cpp`** 中可以看到 Thread 的創建有分為兩種,Java 的創建是呼叫 `createThreadEtc` 函數 (inline 函數) ```cpp= // AndroidThreads.h extern int androidCreateThreadEtc(android_thread_func_t entryFunction, void *userData, const char* threadName, int32_t threadPriority, size_t threadStackSize, android_thread_id_t *threadId); // Create thread with lots of parameters inline bool createThreadEtc(thread_func_t entryFunction, void *userData, const char* threadName = "android:unnamed_thread", int32_t threadPriority = PRIORITY_DEFAULT, size_t threadStackSize = 0, thread_id_t *threadId = nullptr) { return androidCreateThreadEtc(entryFunction, userData, threadName, threadPriority, threadStackSize, threadId) ? true : false; } ``` * createThreadEtc 函數:最終仍會呼叫到 `androidCreateRawThreadEtc`,也就是 **創建一個 pThread 對象** ```cpp= // /libutils/Threads.cpp // 函數指針 static android_create_thread_fn gCreateThreadFn = androidCreateRawThreadEtc; // 實做 int androidCreateThreadEtc(android_thread_func_t entryFunction, void *userData, const char* threadName, int32_t threadPriority, size_t threadStackSize, android_thread_id_t *threadId) { // 查看 gCreateThreadFn return gCreateThreadFn(entryFunction, userData, threadName, threadPriority, threadStackSize, threadId); } // 創建 pThread int androidCreateRawThreadEtc(android_thread_func_t entryFunction, void *userData, const char* threadName __android_unused, int32_t threadPriority, size_t threadStackSize, android_thread_id_t *threadId) { // 創建 pthead 使用的屬性參數 pthread_attr_t attr; pthread_attr_init(&attr); .. 省略部分 errno = 0; // 創建 pthread 對象 pthread_t thread; // @ 追蹤 pthread_create 方法 int result = pthread_create(&thread, &attr, (android_pthread_entry)entryFunction, userData); pthread_attr_destroy(&attr); if (result != 0) { // 創建失敗 Log ... return 0; } if (threadId != nullptr) { *threadId = (android_thread_id_t)thread; // XXX: this is not portable } // 成功返回 1 return 1; } ``` ### 創建 pthread - mmap * 從上面我們知道不管是在 Java 層創建 thread、Native 層創建 thread、啟動時的 BinderThread **最終都會呼叫到 `pthread_create` 方法** ```cpp= // pthread_create.cpp int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr, void* (*start_routine)(void*), void* arg) { ... 省略部分 bionic_tcb* tcb = nullptr; void* child_stack = nullptr; // 為 thread 分配空間 // @ 追蹤 __allocate_thread 方法 int result = __allocate_thread(&thread_attr, &tcb, &child_stack); if (result != 0) { return result; } ... 省略部分 return 0; } ``` * pthread_create#`__allocate_thread` 方法:重點是呼叫 `__allocate_thread_mapping` 方法 ```java= // pthread_create.cpp static int __allocate_thread(pthread_attr_t* attr, bionic_tcb** tcbp, void** child_stack) { ThreadMapping mapping; char* stack_top; bool stack_clean = false; if (attr->stack_base == nullptr) { ... // @ 追蹤 __allocate_thread_mapping 方法 mapping = __allocate_thread_mapping(attr->stack_size, attr->guard_size); // 創建失敗則返回 if (mapping.mmap_base == nullptr) return EAGAIN; ... } else { // @ 追蹤 __allocate_thread_mapping 方法 mapping = __allocate_thread_mapping(0, PTHREAD_GUARD_SIZE); // 創建失敗則返回 if (mapping.mmap_base == nullptr) return EAGAIN; stack_top = static_cast<char*>(attr->stack_base) + attr->stack_size; } // 對齊 stack_top = align_down(stack_top - sizeof(pthread_internal_t), 16); pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top); if (!stack_clean) { // 如果 thread 不由 mmap 分配,那它可能尚未清空,所以這裡會手動清空 thread 空間 memset(thread, 0, sizeof(pthread_internal_t)); } ... 省略部分 return 0; } ``` * 可以看到 `__allocate_thread_mapping` 方法中 **會呼叫 mmap 隨機指定一個空間,為該 thread 動態分配空間** :::info * 如果要查看 mmap 函數的使用,可以用 man 指令 ```shell= man mmap ``` ::: ```java= ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size) { ... 省略部分 const int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE; // 呼叫 mmap 動態拓展空間 char* const space = static_cast<char*>( mmap(nullptr, mmap_size, PROT_NONE, // 分頁不可被訪問 flags, -1, // -1 代表不指定文件偏移,由系統分配 0) ); if (space == MAP_FAILED) { ... 分配失敗訊息 return {}; } ThreadMapping result = {}; result.mmap_base = space; result.mmap_size = mmap_size; result.mmap_base_unguarded = space + stack_guard_size; result.mmap_size_unguarded = mmap_size - stack_guard_size - PTHREAD_GUARD_SIZE; result.static_tls = space + mmap_size - PTHREAD_GUARD_SIZE - layout.size(); result.stack_base = space; result.stack_top = result.static_tls; return result; } ``` ## Appendix & FAQ :::info ::: ###### tags: `Android 系統`