---
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 {
...
}
}
```
> 
### 啟動虛擬機 - 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;
}
```
> 
## 啟動 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;
}
```
> 
### 創建 [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;
}
```
> 
### 初始化 [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;
}
```
> 
### 創建 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 前
> 
* Java 虛擬機啟動時序圖 - 調用到 Runtime 後
> 
## 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 系統`