异常处理有两种情况
- 线程内异常捕获处理
- Signal Catcher 的处理流程
- 线程内异常无法处理的情况
线程内异常捕获处理
异常信号的注册
异常信号的注册 是发生在 zygote进程启动创建art虚拟机时:
app_main.cpp
int main(int argc, char* const argv[]){
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
runtime.start(....);
}
AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){
JniInvocation jni_invocation;
jni_invocation.Init(NULL); //加载相应虚拟机, 并映射相关方法
JNIEnv* env;
//启动虚拟机
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
}
根据soc情况选择加载libart.so还是Dalvik 虚拟机的库, 并映射出虚拟机中的相关method
JniInvocation.cpp
bool JniInvocation::Init(const char* library) {
library = GetLibrary(library, buffer);
const int kDlopenFlags = RTLD_NOW | RTLD_NODELETE;
handle_ = dlopen(library, kDlopenFlags);
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
"JNI_GetDefaultJavaVMInitArgs")) {
return false;
}
if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
"JNI_CreateJavaVM")) {
return false;
}
if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
"JNI_GetCreatedJavaVMs")) {
return false;
}
return true;
}
调用startVm 去启动vm
AndroidRuntime.cpp
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
return -1;
}
}
去art中创建vm 并启动.
/art/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);
RuntimeOptions options;
bool ignore_unrecognized = args->ignoreUnrecognized;
if (!Runtime::Create(options, ignore_unrecognized)) {
return JNI_ERR;
}
android::InitializeNativeLoader();
Runtime* runtime = Runtime::Current();
bool started = runtime->Start();
*p_env = Thread::Current()->GetJniEnv();
*p_vm = runtime->GetJavaVM();
return JNI_OK;
}
创建vm 并出初始化
/art/runtime/runtime.cc
bool Runtime::Create(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
RuntimeArgumentMap runtime_options;
return ParseOptions(raw_options, ignore_unrecognized, &runtime_options) &&
Create(std::move(runtime_options));
}
bool Runtime::Create(RuntimeArgumentMap&& runtime_options) {
instance_ = new Runtime;
Locks::SetClientCallback(IsSafeToCallAbort);
/初始化vm
if (!instance_->Init(std::move(runtime_options))) {
instance_ = nullptr;
return false;
}
return true;
}
在vm初始化时, 会注册相关异常信号
bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
fault_manager.Init();
}
/art/runtime/fault_handler.cc
void FaultManager::Init() {
CHECK(!initialized_);
sigset_t mask;
sigfillset(&mask);
sigdelset(&mask, SIGABRT);
sigdelset(&mask, SIGBUS);
sigdelset(&mask, SIGFPE);
sigdelset(&mask, SIGILL);
sigdelset(&mask, SIGSEGV);
SigchainAction sa = {
.sc_sigaction = art_fault_handler,
.sc_mask = mask,
.sc_flags = 0UL,
};
AddSpecialSignalHandlerFn(SIGSEGV, &sa);
initialized_ = true;
}
由以上流程可以知道相关异常信号,在art虚拟机启动时,就已经注册到系统里面了.
异常信号的捕获与处理
因为相关异常信号已经注册到系统中, 所以相关异常信号产生时,会走此handle中
/art/runtime/fault_handler.cc
static bool art_fault_handler(int sig, siginfo_t* info, void* context) {
return fault_manager.HandleFault(sig, info, context);
}
bool FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
if (IsInGeneratedCode(info, context, true)) {
VLOG(signals) << "in generated code, looking for handler";
for (const auto& handler : generated_code_handlers_) {
VLOG(signals) << "invoking Action on handler " << handler;
if (handler->Action(sig, info, context)) {
return true;
}
}
}
art_sigsegv_fault();
return false;
}
generated_code_handlers_的填充是:
// Null pointer fault handler
NullPointerHandler::NullPointerHandler(FaultManager* manager) : FaultHandler(manager) {
manager_->AddHandler(this, true);
}
// Suspension fault handler
SuspensionHandler::SuspensionHandler(FaultManager* manager) : FaultHandler(manager) {
manager_->AddHandler(this, true);
}
// Stack overflow fault handler
StackOverflowHandler::StackOverflowHandler(FaultManager* manager) : FaultHandler(manager) {
manager_->AddHandler(this, true);
}
通过以上流程可知, 在发生异常时, 会走到对应的Handler 的Action 方法内,
在往后的流程 就和 https://blog.csdn.net/xiaolli/article/details/115088191 一样了
Signal Catcher 的流程
Signal Catcher 线程是在 进程fork是起来的, 大概流程为
public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) {
VM_HOOKS.preFork();
resetNicePriority();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir);
VM_HOOKS.postForkCommon();
return pid;
}
frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(***)
capabilities &= GetEffectiveCapabilityMask(env);
return ForkAndSpecializeCommon(env, uid, gid, gids, runtime_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
se_name, false, fdsToClose, fdsToIgnore, is_child_zygote == JNI_TRUE,
instructionSet, appDataDir);
}
static pid_t ForkAndSpecializeCommon(***){
SetSignalHandlers();
UnsetChldSignalHandler();
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, is_system_server, is_child_zygote, instructionSet);
}
frameworks/base/core/java/com/android/internal/os/Zygote.java
private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer,
boolean isZygote, String instructionSet) {
VM_HOOKS.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
}
libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
public void postForkChild(int runtimeFlags, boolean isSystemServer, boolean isZygote,
String instructionSet) {
nativePostForkChild(token, runtimeFlags, isSystemServer, isZygote, instructionSet);
Math.setRandomSeedInternal(System.currentTimeMillis());
}
art/runtime/native/dalvik_system_ZygoteHooks.cc
static void ZygoteHooks_nativePostForkChild(***){
Runtime::Current()->InitNonZygoteOrPostFork( env, is_system_server, action, isa_string.c_str());
}
在runtime中启动 SignalCatcher 线程
art/runtime/runtime.cc
void Runtime::InitNonZygoteOrPostFork(***){
StartSignalCatcher();
}
void Runtime::StartSignalCatcher() {
if (!is_zygote_) {
signal_catcher_ = new SignalCatcher(stack_trace_file_, use_tombstoned_traces_);
}
}
启动SignalCatcher 线程
art/runtime/signal_catcher.cc
SignalCatcher::SignalCatcher(),thread_(nullptr) {
SetHaltFlag(false);
//启动SignalCatcher线程
CHECK_PTHREAD_CALL(pthread_create, (&pthread_, nullptr, &Run, this), "signal catcher thread");
Thread* self = Thread::Current();
MutexLock mu(self, lock_);
while (thread_ == nullptr) {
cond_.Wait(self);
}
}
void* SignalCatcher::Run(void* arg) {
SignalCatcher* signal_catcher = reinterpret_cast<SignalCatcher*>(arg);
Runtime* runtime = Runtime::Current();
CHECK(runtime->AttachCurrentThread("Signal Catcher", true, runtime->GetSystemThreadGroup(),
!runtime->IsAotCompiler()));
Thread* self = Thread::Current();
SignalSet signals;
signals.Add(SIGQUIT);
signals.Add(SIGUSR1);
//循环等待处理抛过来的SIGQUIT\SIGQUIT这两个信号
while (true) {
int signal_number = signal_catcher->WaitForSignal(self, signals);
if (signal_catcher->ShouldHalt()) {
runtime->DetachCurrentThread();
return nullptr;
}
switch (signal_number) {
case SIGQUIT:
signal_catcher->HandleSigQuit();
break;
case SIGUSR1:
signal_catcher->HandleSigUsr1();
break;
default:
LOG(ERROR) << "Unexpected signal %d" << signal_number;
break;
}
}
}
线程内异常无法处理的情况
线程内异常无法自行消化的流程,涉及到了线程的创建:
线程创建流程为:
Thread thread = new Thread();
thread.start();
libcore/ojluni/src/main/java/java/lang/Thread.java
public synchronized void start() {
nativeCreate(this, stackSize, daemon);
}
/art/runtime/native/java_lang_Thread.cc
static void Thread_nativeCreate(JNIEnv* env, jclass, jobject java_thread, jlong stack_size,
jboolean daemon) {
Runtime* runtime = Runtime::Current();
Thread::CreateNativeThread(env, java_thread, stack_size, daemon == JNI_TRUE);
}
art/runtime/thread.cc
void Thread::CreateNativeThread(JNIEnv* env, jobject java_peer, size_t stack_size, bool is_daemon) {
//创建线程,并在线程创建成功之后, 执行CreateCallback 方法
pthread_create_result = pthread_create(&new_pthread, &attr, Thread::CreateCallback, child_thread);
}
//线程创建成功后的起始函数
void* Thread::CreateCallback(void* arg) {
Thread* self = reinterpret_cast<Thread*>(arg);
Runtime* runtime = Runtime::Current();
{
ScopedObjectAccess soa(self);
self->InitStringEntryPoints();
self->tlsPtr_.opeer = soa.Decode<mirror::Object>(self->tlsPtr_.jpeer).Ptr();
self->GetJniEnv()->DeleteGlobalRef(self->tlsPtr_.jpeer);
self->tlsPtr_.jpeer = nullptr;
self->SetThreadName(self->GetThreadName()->ToModifiedUtf8().c_str());
ArtField* priorityField = jni::DecodeArtField(WellKnownClasses::java_lang_Thread_priority);
self->SetNativePriority(priorityField->GetInt(self->tlsPtr_.opeer));
runtime->GetRuntimeCallbacks()->ThreadStart(self);
ObjPtr<mirror::Object> receiver = self->tlsPtr_.opeer;
//获取Thread的run方法, 并调用run方法
jmethodID mid = WellKnownClasses::java_lang_Thread_run;
ScopedLocalRef<jobject> ref(soa.Env(), soa.AddLocalReference<jobject>(receiver));
InvokeVirtualOrInterfaceWithJValues(soa, ref.get(), mid, nullptr);
}
//因为各种原因run方法被中断,需要销毁此thread,
//常见的是Thread发生异常, thread自身没有catch到, run方法被中断, 会走到这里销毁线程
Runtime::Current()->GetThreadList()->Unregister(self);
return nullptr;
}
线程销毁时,异常的分发处理流程为:
//从thread_list unregister 本线程,并销毁本线程
art/runtime/thread_list.cc
void ThreadList::Unregister(Thread* self) {
self->Destroy();
}
//销毁线程,并handler分发 线程中的excetpion 异常
/art/runtime/thread.cc
void Thread::Destroy() {
HandleUncaughtExceptions(soa);
}
void Thread::HandleUncaughtExceptions(ScopedObjectAccessAlreadyRunnable& soa) {
if (!IsExceptionPending()) {
return; // 线程中不存在异常, return 直接销毁异常
}
ScopedLocalRef<jobject> peer(tlsPtr_.jni_env, soa.AddLocalReference<jobject>(tlsPtr_.opeer));
ScopedThreadStateChange tsc(this, kNative);
// Get and clear the exception.
ScopedLocalRef<jthrowable> exception(tlsPtr_.jni_env, tlsPtr_.jni_env->ExceptionOccurred());
tlsPtr_.jni_env->ExceptionClear();
// 线程中存在异常, 回调java 的dispatchUncaughtException(Throwable)去分发处理异常
tlsPtr_.jni_env->CallVoidMethod(peer.get(),
WellKnownClasses::java_lang_Thread_dispatchUncaughtException,
exception.get());
tlsPtr_.jni_env->ExceptionClear();
}
libcore/ojluni/src/main/java/java/lang/Thread.java
//java 中分发处理异常 是先调用setUncaughtExceptionPreHandler 设置的handler
//在看setUncaughtExceptionHandler 是否有设置,
public final void dispatchUncaughtException(Throwable e) {
Thread.UncaughtExceptionHandler initialUeh =
Thread.getUncaughtExceptionPreHandler(); //setUncaughtExceptionPreHandler
if (initialUeh != null) {
try {
initialUeh.uncaughtException(this, e);
} catch (RuntimeException | Error ignored) {
}
}
getUncaughtExceptionHandler().uncaughtException(this, e);
}
//如果setUncaughtExceptionHandler 有设置,那么会调用 设置handler去 分发异常,
//如果没有设置,会走ThreadGroup去分发 exception
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
app没有设置setUncaughtExceptionHandler 的情况
/libcore/ojluni/src/main/java/java/lang/ThreadGroup.java
public void uncaughtException(Thread t, Throwable e) {
//会去拿setDefaultUncaughtExceptionHandler 设置的DefaultHandler
//如果DefaultHandler 也没有拿到, 那么会在 logcat中打印log结束
Thread.UncaughtExceptionHandler ueh =
Thread.getDefaultUncaughtExceptionHandler();
if (ueh != null) {
ueh.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
System.err.print("Exception in thread \""
+ t.getName() + "\" ");
e.printStackTrace(System.err);
}
}