android 异常处理流程

异常处理有两种情况

  • 线程内异常捕获处理
  • 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);
        }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 应用程序中,如果发生异常导致应用程序崩溃或关闭,可以通过捕获异常并在异常处理代码中进行重启应用程序的操作来实现应用程序的自动重启。下面是一个简单的实现方式: 1. 定义一个类来捕获应用程序的未捕获异常: ```java public class RestartExceptionHandler implements Thread.UncaughtExceptionHandler { private Context mContext; public RestartExceptionHandler(Context context) { mContext = context; } @Override public void uncaughtException(Thread t, Throwable e) { // 在这里进行应用程序的重启操作 restartApp(); } private void restartApp() { Intent intent = new Intent(mContext, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivity(intent); android.os.Process.killProcess(android.os.Process.myPid()); System.exit(0); } } ``` 在这个类中,我们重写了 `Thread.UncaughtExceptionHandler` 接口的 `uncaughtException` 方法,当应用程序发生未捕获的异常时,该方法会被调用。在这个方法中,我们调用 `restartApp` 方法来重启应用程序。 2. 在应用程序的 `Application` 类中设置异常处理器: ```java public class MyApp extends Application { @Override public void onCreate() { super.onCreate(); Thread.setDefaultUncaughtExceptionHandler(new RestartExceptionHandler(this)); } } ``` 在这个类中,我们通过调用 `Thread.setDefaultUncaughtExceptionHandler` 方法来设置应用程序的异常处理器为 `RestartExceptionHandler` 类。 通过上述方式设置异常处理器,当应用程序发生未捕获的异常时,会自动重启应用程序。需要注意的是,这种方式只适用于应用程序发生未捕获的异常时的重启,如果应用程序正常关闭,或者是用户主动关闭应用程序,是不会触发重启操作的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值