android.os.DeadSystemException

来源:互联网 发布:phaser.js 编辑:程序博客网 时间:2024/06/16 23:32

这种异常只发生在7.0以上系统,通常与service的启动有关,目前暂时无能为力。

google issue上有人提了这个问题:https://issuetracker.google.com/issues/62609337

下面的分析是别人写的,我拷贝到这里来,感谢以下分析的作者。


----------------------------别人的分析---------------------------

先看一下DeadSystemException的定义

package android.os;
/**
 * The core Android system has died and is going through a runtime restart. All
 * running apps will be promptly killed.
 */
public class DeadSystemException extends DeadObjectException {
    public DeadSystemException() {
        super();
    }
}

在源码中有一段注释,翻译过来就是:Android核心系统挂了,正在进行运行时重启,所有运行中的app都会被杀死。

看到这里已经基本可以确认,app基本做不了什么,但是会引出一个疑问,会不会是由于我们自己的app运行中出现了问题,导致了Android核心系统挂掉了。

通过日志可以看到最后一个方法调用是在ActivityThread的handleCreateService方法中,在这里要说下ActivityThread

/**
 * This manages the execution of the main thread in an
 * application process, scheduling and executing activities,
 * broadcasts, and other operations on it as the activity
 * manager requests.
 *
 * {@hide}
 */
public final class ActivityThread {
...
}

可以看到注释中描述,这个类主要是管理Activity和Service等的生命周期,运行在主线程,其实我自己理解,ActivityThread就代表了主线程;Activity和Service等的组件从创建到销毁,都是ActivityThread来调度的,说到ActivityThread,不得不提一下ActivityManagerService,AMS作为系统服务,运行在System进程中,启动应用,销毁应用等都需要AMS来调度,这就又引出了Binder机制,额,好像跑偏了;总结一下就是如果调用了startService,首先处理的是AMS,然后通过跨进程调用ActivityThread调用Service的生命周期函数。

好了,继续回到堆栈,找到handleCreateService方法:

private void handleCreateService(CreateServiceData data) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    LoadedApk packageInfo = getPackageInfoNoCheck(
            data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = (Service) cl.loadClass(data.info.name).newInstance();
    catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to instantiate service " + data.info.name
                ": " + e.toString(), e);
        }
    }
    try {
        if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        service.attach(context, this, data.info.name, data.token, app,
                ActivityManagerNative.getDefault());
        service.onCreate();
        mServices.put(data.token, service);
        try {
            ActivityManagerNative.getDefault().serviceDoneExecuting(
                    data.token, SERVICE_DONE_EXECUTING_ANON, 00);
        catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to create service " + data.info.name
                ": " + e.toString(), e);
        }
    }
}

其实就是在这一块抛出来的RuntimeException,

if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to create service " + data.info.name
                ": " + e.toString(), e);
  }

究其原因还是因为在try内部还有一个try catch,然而在catch住RemoteException之后,又throw了一个新的Exception,具体是什么,我们来看一下RemoteException源码:

package android.os;
import android.util.AndroidException;
/**
 * Parent exception for all Binder remote-invocation errors
 */
public class RemoteException extends AndroidException {
    public RemoteException() {
        super();
    }
    public RemoteException(String message) {
        super(message);
    }
    /** {@hide} */
    public RuntimeException rethrowAsRuntimeException() {
        throw new RuntimeException(this);
    }
    /**
     * Rethrow this exception when we know it came from the system server. This
     * gives us an opportunity to throw a nice clean
     * {@link DeadSystemException} signal to avoid spamming logs with
     * misleading stack traces.
     * <p>
     * Apps making calls into the system server may end up persisting internal
     * state or making security decisions based on the perceived success or
     * failure of a call, or any default values returned. For this reason, we
     * want to strongly throw when there was trouble with the transaction.
     *
     * @hide
     */
    public RuntimeException rethrowFromSystemServer() {
        if (this instanceof DeadObjectException) {
            throw new RuntimeException(new DeadSystemException());
        else {
            throw new RuntimeException(this);
        }
    }
}

可以看到在rethrowFromSystemServer方法中又抛出了一个DeadSystemException,这就是上报crash的堆栈信息

据此,我们可以判定,是在执行下面代码的时候出现了异常

ActivityManagerNative.getDefault().serviceDoneExecuting(
                    data.token, SERVICE_DONE_EXECUTING_ANON, 00);

据此,只能说无能为力了


原创粉丝点击