基于Android 7.0源码分析,涉及的主要源码如下
~/aosp/libcore/ojluni/src/main/java/java/lang/Thread.java
~/aosp/art/runtime/native/java_lang_Thread.cc
~/aosp/art/runtime/thread.cc
~/aosp/art/runtime/jni_env_ext.cc
~/aosp/art/runtime/jni_internal.cc
~/aosp/art/runtime/reflection.cc
~/aosp/bionic/libc/bionic/pthread_create.cpp
~/aosp/bionic/libc/bionic/pthread_internal.cpp
Java线程的启动方式
(1)
new Thread() {
@Override
public void run() {
// Do something
}
}.start();
(2)
new Thread(new Runnable() {
@Override
public void run() {
// Do something
}
}).start();
两种方式原理相同,下面以(1)方式为例分析。
Java线程创建的过程
下面从Thread
的构造函数开始分析。
public Thread() {
// 对于匿名线程,线程名为“Thread-xxx(整数)”
init(null, null, "Thread-" + nextThreadNum(), 0);
}
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
// 新线程的父线程
Thread parent = currentThread();
if (g == null) {
g = parent.getThreadGroup();
}
g.addUnstarted();
this.group = g;
this.target = target;
// 线程优先级,映射到linux进程优先级
this.priority = parent.getPriority();
// 是否为守护线程
this.daemon = parent.isDaemon();
// 设置线程名,并未真正执行
setName(name);
// 设置线程上下文类加载器,通常为应用类加载器
init2(parent);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
// 线程序列号
tid = nextThreadID();
}
Thread
的构造方法相对简单,只是简单设置线程参数,下面看Thread
的start
方法。
public synchronized void start() {
......
// 添加到线程组,修改统计信息
group.add(this);
started = false;
try {
// 创建启动线程
nativeCreate(this, stackSize, daemon);
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
nativeCreate
是个Native方法,它的实现在java_lang_Thread.cc
中。
static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size,
jboolean daemon) {
// There are sections in the zygote that forbid thread creation.
Runtime* runtime = Runtime::Current();
// 不能在Zygote进程的初始阶段创建线程
if (runtime->IsZygote() && runtime->IsZygoteNoThreadSection()) {
jclass internal_error = env->FindClass("java/lang/InternalError");
CHECK(internal_error != nullptr);
env->ThrowNew(internal_error, "Cannot create threads in zygote");
return;
}
Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);
}
void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) {
CHECK(java_peer != nullptr);
Thread* self = static_cast<JNIEnvExt*>(env)->self;
......
Runtime* runtime = Runtime::Current();
......
// 为新线程创建Native层的Thread对象
Thread* child_thread = new Thread(is_daemon);
// Use global JNI ref to hold peer live while child thread starts.
// 创建JNI全局引用
child_thread->tlsPtr_.jpeer = env->NewGlobalRef(java_peer);
// 计算线程栈的大小,这里stack_size = 1040KB
stack_size = FixStackSize(stack_size);
// Thread.start is synchronized, so we know that nativePeer is 0, and know that we're not racing to
// assign it.
// Native Thread对象地址保存到Java Thread对象的nativePeer域
env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
reinterpret_cast<jlong>(child_thread));
// Try to allocate a JNIEnvExt for the thread. We do this here as we might be out of memory and
// do not have a good way to report this on the child's side.
// 创建JNIEnvExt
std::unique_ptr<JNIEnvExt> child_jni_env_ext(
JNIEnvExt::Create(child_thread, Runtime::Current()->GetJavaVM()));
int pthread_create_result = 0;
if (child_jni_env_ext.get() != nullptr) {
pthread_t new_pthread;
pthread_attr_t attr;
// 保存JNIEnvExt
child_thread->tlsPtr_.tmp_jni_env = child_jni_env_ext.get();
// 调用pthread_attr_init初始化线程属性
CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), "new thread");
// 调用pthread_attr_setdetachstate设置state为PTHREAD_ATTR_FLAG_DETACHED
CHECK_PTHREAD_CALL(pthread_attr_setdetachstate, (&attr, PTHREAD_CREATE_DETACHED),
"PTHREAD_CREATE_DETACHED");
// 调用pthread_attr_setstacksize设置栈大小到线程属性中
CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), stack_size);
// 创建新的线程,线程启动后调用Thread::CreateCallback方法
pthread_create_result = pthread_create(&new_pthread,
&attr,
Thread::CreateCallback,
child_thread);
CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread");
......
}
......
}
下面首先分析线程栈大小的计算,接下来分析JNIEnvExt
的创建,最后看pthread_create
的实现
static size_t FixStackSize(size_t stack_size) {
// A stack size of zero means "use the default".
if (stack_size == 0) {
// 系统默认的栈大小为0
stack_size = Runtime::Current()->GetDefaultStackSize();
}
// Dalvik used the bionic pthread default stack size for native threads,
// so include that here to support apps that expect large native stacks.
// 加上1MB用作Native stack
stack_size += 1 * MB;
......
if (Runtime::Current()->ExplicitStackOverflowChecks()) {
// It's likely that callers are trying to ensure they have at least a certain amount of
// stack space, so we should add our reserved space on top of what they requested, rather
// than implicitly take it away from them.
stack_size += GetStackOverflowReservedBytes(kRuntimeISA);
} else {
// If we are going to use implicit stack checks, allocate space for the protected
// region at the bottom of the stack.
// 加上(8K + 8K)
stack_size += Thread::kStackOverflowImplicitCheckSize +
GetStackOverflowReservedBytes(kRuntimeISA);
}
// Some systems require the stack size to be a multiple of the system page size, so round up.
stack_size = RoundUp(stack_size, kPageSize);
// stack_size = 1040KB
return stack_size;
}
这里虚拟机栈与Native栈共用。下面看JNIEnvExt
的创建。
JNIEnvExt* JNIEnvExt::Create(Thread* self_in, JavaVMExt* vm_in) {
std::unique_ptr<JNIEnvExt> ret(new JNIEnvExt(self_in, vm_in));
if (CheckLocalsValid(ret.get())) {
return ret.release();
}
return nullptr;
}
JNIEnvExt::JNIEnvExt(Thread* self_in, JavaVMExt* vm_in)
: self(self_in),
vm(vm_in),
local_ref_cookie(IRT_FIRST_SEGMENT),
// JNI本地引用表
locals(kLocalsInitial, kLocalsMax, kLocal, false),
check_jni(false),
runtime_deleted(false),
critical(0),
monitors("monitors", kMonitorsInitial, kMonitorsMax) {
// 初始化JNINativeInterface(实现在jni_internal.cc中)
functions = unchecked_functions = GetJniNativeInterface();
if (vm->IsCheckJniEnabled()) {
SetCheckJniEnabled(true);
}
}
- JNIEnvExt管理JNI本地引用表
- JavaVMExt管理JNI全局引用表
下面看pthread_create
的实现
int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
void* (*start_routine)(void*), void* arg) {
......
pthread_attr_t thread_attr;
if (attr == NULL) {
pthread_attr_init(&thread_attr);
} else {
thread_attr = *attr;
attr = NULL; // Prevent misuse below.
}
pthread_internal_t* thread = NULL;
void* child_stack = NULL;
// 分配新(子)线程栈空间以及初始化TLS
int result = __allocate_thread(&thread_attr, &thread, &child_stack);
if (result != 0) {
return result;
}
// 用于父线程与子线程同步
thread->startup_handshake_lock.init(false);
thread->startup_handshake_lock.lock();
// 入口函数
thread->start_routine = start_routine;
// 入口函数参数
thread->start_routine_arg = arg;
......
// clone新的进程(线程),线程启动后执行__pthread_start
int rc = clone(__pthread_start, child_stack, flags, thread, &(thread->tid), tls, &(thread->tid));
......
// pthread_internal_t添加到全局g_thread_list中
*thread_out = __pthread_internal_add(thread);
// 解锁让新线程运行
thread->startup_handshake_lock.unlock();
return 0;
}
static int __allocate_thread(pthread_attr_t* attr, pthread_internal_t** threadp, void** child_stack) {
size_t mmap_size;
uint8_t* stack_top;
if (attr->stack_base == NULL) {
// The caller didn't provide a stack, so allocate one.
// Make sure the stack size and guard size are multiples of PAGE_SIZE.
// 32位系统中1KB < sizeof(pthread_internal_t) < 2KB
// 64为系统上2KB < sizeof(pthread_internal_t) < 3KB
// mmap_size = 1044KB
mmap_size = BIONIC_ALIGN(attr->stack_size + sizeof(pthread_internal_t), PAGE_SIZE);
// guard_size = 4K
attr->guard_size = BIONIC_ALIGN(attr->guard_size, PAGE_SIZE);
// 映射线程栈空间
attr->stack_base = __create_thread_mapped_space(mmap_size, attr->guard_size);
if (attr->stack_base == NULL) {
return EAGAIN;
}
stack_top = reinterpret_cast<uint8_t*>(attr->stack_base) + mmap_size;
} else {
// Remember the mmap size is zero and we don't need to free it.
mmap_size = 0;
stack_top = reinterpret_cast<uint8_t*>(attr->stack_base) + attr->stack_size;
}
// 调整栈顶,为了安全访问pthread_internal_t和线程栈,边界进行16字节对齐
stack_top = reinterpret_cast<uint8_t*>(
(reinterpret_cast<uintptr_t>(stack_top) - sizeof(pthread_internal_t)) & ~0xf);
pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top);
if (mmap_size == 0) {
// If thread was not allocated by mmap(), it may not have been cleared to zero.
// So assume the worst and zero it.
memset(thread, 0, sizeof(pthread_internal_t));
}
// 更新stack_size
attr->stack_size = stack_top - reinterpret_cast<uint8_t*>(attr->stack_base);
thread->mmap_size = mmap_size;
// 线程属性拷贝至线程TLS
thread->attr = *attr;
// 初始化TLS
__init_tls(thread);
*threadp = thread;
*child_stack = stack_top;
return 0;
}
小结
-
Android Java线程栈内存空间布局
从stack_begin到stack_end的8KB空间,如果调用Java方法且栈顶指针sp位于stack_end之下则抛出栈溢出错误,此时仍然可以调用Native方法。stack_begin之下的4KB空间,处理栈溢出错误时可能使用。
-
Java线程栈内存映射
Java线程启动后执行Thread
的run
方法的过程
static int __pthread_start(void* arg) {
pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(arg);
// Wait for our creating thread to release us. This lets it have time to
// notify gdb about this thread before we start doing anything.
// This also provides the memory barrier needed to ensure that all memory
// accesses previously made by the creating thread are visible to us.
// 等待父线程释放锁
thread->startup_handshake_lock.lock();
// 创建信号栈
__init_alternate_signal_stack(thread);
// 调用start_routine,也就是Thread::CreateCallback方法
void* result = thread->start_routine(thread->start_routine_arg);
pthread_exit(result);
return 0;
}
void __init_alternate_signal_stack(pthread_internal_t* thread) {
// Create and set an alternate signal stack.
// 映射信号栈地址空间(16KB + 4KB)
void* stack_base = mmap(NULL, SIGNAL_STACK_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (stack_base != MAP_FAILED) {
// Create a guard page to catch stack overflows in signal handlers.
// 创建guard page(4KB)捕获信号栈溢出
if (mprotect(stack_base, PAGE_SIZE, PROT_NONE) == -1) {
munmap(stack_base, SIGNAL_STACK_SIZE);
return;
}
stack_t ss;
// 信号栈起始地址
ss.ss_sp = reinterpret_cast<uint8_t*>(stack_base) + PAGE_SIZE;
// 信号栈大小
ss.ss_size = SIGNAL_STACK_SIZE - PAGE_SIZE;
ss.ss_flags = 0;
// 通知内核信号栈信息
sigaltstack(&ss, NULL);
thread->alternate_signal_stack = stack_base;
// We can only use const static allocated string for mapped region name, as Android kernel
// uses the string pointer directly when dumping /proc/pid/maps.
// 设置虚拟内存区域名称
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ss.ss_sp, ss.ss_size, "thread signal stack");
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, stack_base, PAGE_SIZE, "thread signal stack guard page");
}
}
-
信号栈映射信息
下面看Thread::CreateCallback
的实现
void* Thread::CreateCallback(void* arg) {
Thread* self = reinterpret_cast<Thread*>(arg);
Runtime* runtime = Runtime::Current();
.....
{
......
// 调用Thread的Init方法
CHECK(self->Init(runtime->GetThreadList(), runtime->GetJavaVM(), self->tlsPtr_.tmp_jni_env));
self->tlsPtr_.tmp_jni_env = nullptr;
......
}
{
ScopedObjectAccess soa(self);
// 初始化字符串构造入口
self->InitStringEntryPoints();
// Copy peer into self, deleting global reference when done.
CHECK(self->tlsPtr_.jpeer != nullptr);
// opeer指向Java Thread对象在堆中的镜像
self->tlsPtr_.opeer = soa.Decode<mirror::Object*>(self->tlsPtr_.jpeer);
self->GetJniEnv()->DeleteGlobalRef(self->tlsPtr_.jpeer);
self->tlsPtr_.jpeer = nullptr;
// 设置线程名
self->SetThreadName(self->GetThreadName(soa)->ToModifiedUtf8().c_str());
ArtField* priorityField = soa.DecodeField(WellKnownClasses::java_lang_Thread_priority);
// Java线程优先级转换为Linux进程优先级
self->SetNativePriority(priorityField->GetInt(self->tlsPtr_.opeer));
Dbg::PostThreadStart(self);
// Invoke the 'run' method of our java.lang.Thread.
// 调用Java Thread对象的run方法
mirror::Object* receiver = self->tlsPtr_.opeer;
jmethodID mid = WellKnownClasses::java_lang_Thread_run;
ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
InvokeVirtualOrInterfaceWithJValues(soa, ref.get(), mid, nullptr);
}
// Detach and delete self.
Runtime::Current()->GetThreadList()->Unregister(self);
return nullptr;
}
bool Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm, JNIEnvExt* jni_env_ext) {
// This function does all the initialization that must be run by the native thread it applies to.
// (When we create a new thread from managed code, we allocate the Thread* in Thread::Create so
// we can handshake with the corresponding native thread when it's ready.) Check this native
// thread hasn't been through here already...
CHECK(Thread::Current() == nullptr);
// Set pthread_self_ ahead of pthread_setspecific, that makes Thread::Current function, this
// avoids pthread_self_ ever being invalid when discovered from Thread::Current().
tlsPtr_.pthread_self = pthread_self();
CHECK(is_started_);
// 实现在thread_android.cc中,空函数
SetUpAlternateSignalStack();
// 获取栈信息并设置隐式栈溢出保护
if (!InitStackHwm()) {
return false;
}
InitCpu();
// 初始化JNI以及Quick entrypoints
InitTlsEntryPoints();
RemoveSuspendTrigger();
InitCardTable();
InitTid();
// Mterp解释器信息保存到TLS
interpreter::InitInterpreterTls(this);
#ifdef ART_TARGET_ANDROID
// 线程本地存储(在pthread_internal_t内部)
__get_tls()[TLS_SLOT_ART_THREAD_SELF] = this;
#else
CHECK_PTHREAD_CALL(pthread_setspecific, (Thread::pthread_key_self_, this), "attach self");
#endif
DCHECK_EQ(Thread::Current(), this);
tls32_.thin_lock_thread_id = thread_list->AllocThreadId(this);
if (jni_env_ext != nullptr) {
DCHECK_EQ(jni_env_ext->vm, java_vm);
DCHECK_EQ(jni_env_ext->self, this);
tlsPtr_.jni_env = jni_env_ext;
} else {
tlsPtr_.jni_env = JNIEnvExt::Create(this, java_vm);
if (tlsPtr_.jni_env == nullptr) {
return false;
}
}
// 线程添加到thread_list
thread_list->Register(this);
return true;
}
bool Thread::InitStackHwm() {
void* read_stack_base;
size_t read_stack_size;
size_t read_guard_size;
// 从线程本地存储中获取线程栈信息
GetThreadStack(tlsPtr_.pthread_self, &read_stack_base, &read_stack_size, &read_guard_size);
tlsPtr_.stack_begin = reinterpret_cast<uint8_t*>(read_stack_base);
tlsPtr_.stack_size = read_stack_size;
......
// 设置stack_end = stack_begin + 8KB
ResetDefaultStackEnd();
// Install the protected region if we are doing implicit overflow checks.
if (implicit_stack_check && !valgrind_on_arm) {
// The thread might have protected region at the bottom. We need
// to install our own region so we need to move the limits
// of the stack to make room for it.
// 调整stack_begin、stack_end以及stack_size,通常read_guard_size + kStackOverflowProtectedSize = 8KB
tlsPtr_.stack_begin += read_guard_size + kStackOverflowProtectedSize;
tlsPtr_.stack_end += read_guard_size + kStackOverflowProtectedSize;
tlsPtr_.stack_size -= read_guard_size;
InstallImplicitProtection();
}
// Sanity check.
CHECK_GT(FindStackTop(), reinterpret_cast<void*>(tlsPtr_.stack_end));
return true;
}
下面看InvokeVirtualOrInterfaceWithJValues
的实现
JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa,
jobject obj, jmethodID mid, jvalue* args) {
// We want to make sure that the stack is not within a small distance from the
// protected region in case we are calling into a leaf function whose stack
// check has been elided.
// 编译器内建函数__builtin_frame_address(0)返回当前函数的帧地址
// See http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html
if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) {
// 当前的栈顶地址低于stack_end,抛出栈溢出错误
ThrowStackOverflowError(soa.Self());
return JValue();
}
// 解引用获取堆中的镜像
mirror::Object* receiver = soa.Decode<mirror::Object*>(obj);
// 获取run方法的ArtMethod
ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
if (is_string_init) {
// Replace calls to String.<init> with equivalent StringFactory call.
// 如果是Java String类的构造方法,替换为StringFactory的构造方法
method = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid));
receiver = nullptr;
}
uint32_t shorty_len = 0;
const char* shorty =
method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
JValue result;
ArgArray arg_array(shorty, shorty_len);
arg_array.BuildArgArrayFromJValues(soa, receiver, args);
// 调用Thread的run方法
InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
if (is_string_init) {
// For string init, remap original receiver to StringFactory result.
UpdateReference(soa.Self(), obj, result.GetL());
}
return result;
}
文中涉及Android ART运行时原理的一些知识暂不详细讨论,以后研究ART运行时再做分析。
网友评论