10

看起来像这样的异常令人困惑:

FATAL EXCEPTION: main
java.lang.NullPointerException
    at android.os.Parcel.readException(Parcel.java:1437)
    at android.os.Parcel.readException(Parcel.java:1385)
    at com.yourpackage.ipc.IYourClass$Stub$Proxy.yourMethod(IYourClass.java:488)
    at com.yourpackage.ipc.YourClassShim.yourMethod(YourClassShim.java:269)

我发现了一堆相关的问题,但没有一个答案是“你如何调试这个”。所以我提出这个问题/答案。

通过查看此处此处的 android 源代码,您会发现它可以抛出任何这些(NullPointerException 正是我所拥有的):

SecurityException(msg);
BadParcelableException(msg);
IllegalArgumentException(msg);
NullPointerException(msg);
IllegalStateException(msg);
RuntimeException("Unknown exception code: " + code + " msg " + msg);

但这些是什么原因造成的?

4

2 回答 2

22

这里发生的readException()是检查 IPC 字节流中是否有表明发生异常的标头;如果找到,则抛出该类型的新异常,并带有相同的消息,但缺少原始堆栈跟踪。(它实际上只知道一些异常类型;其他任何东西都被翻译成 base RuntimeException。)

那么最初的异常是从哪里来的呢?嗯,在真正实现的核心的某个地方YourClass.yourMethod()——不是在任何可打包或 IPC 代码中。所以去那里,将整个方法包装在一个 try/catch 中,并记录你捕获的任何内容。

(或者如果你有远程进程断点工作,则在那里设置一个断点。)

于 2013-09-17T19:28:57.643 回答
0

我认为android应该提供更多binder远程异常信息

所以我修改 Parcel.java 来包装更多的活页夹远程异常信息

public final void writeException(Exception e) {
    int code = 0;
    if (e instanceof SecurityException) {
        code = EX_SECURITY;
    } else if (e instanceof BadParcelableException) {
        code = EX_BAD_PARCELABLE;
    } else if (e instanceof IllegalArgumentException) {
        code = EX_ILLEGAL_ARGUMENT;
    } else if (e instanceof NullPointerException) {
        code = EX_NULL_POINTER;
    } else if (e instanceof IllegalStateException) {
        code = EX_ILLEGAL_STATE;
    }
    writeInt(code);
    StrictMode.clearGatheredViolations();
    if (code == 0) {
        if (e instanceof RuntimeException) {
            throw (RuntimeException) e;
        }
        throw new RuntimeException(e);
    }
    // I replace writeString(e.getMessage()) with writeString(remoteExceptionToString(e))
    writeString(remoteExceptionToString(e));
}

static String remoteExceptionToString(Exception e) {
    final StringWriter sw = new StringWriter(1024);
    final PrintWriter pw = new PrintWriter(sw, true);
    pw.println();
    e.printStackTrace(pw);
    return sw.toString().replace("\n", String.format("\n(%5d %5d): ", Process.myPid(), Process.myTid()));
}

SerializeExceptionSecondService 定义:

public class SerializeExceptionSecondService extends Service {
private static final String TAG = "SerializeExceptionSecondService";

public SerializeExceptionSecondService() {
}

@Override
public IBinder onBind(Intent intent) {
    // TODO: Return the communication channel to the service.
    return mServiceBinder;
}

private final ISerializeExceptionSecondService.Stub mServiceBinder = new ISerializeExceptionSecondService.Stub() {

    @Override
    public void throwException() throws RemoteException {
        // TODO Auto-generated method stub
        Log.e(TAG, "throwException");
        throw new IllegalStateException("Cause1", new IllegalStateException("Cause2", new IllegalStateException("Cause3")));
    }

    @Override
    public void noThrowException() throws RemoteException {
        // TODO Auto-generated method stub

    }
};
}

AndroidManifest.xml 片段:

    <service
        android:name=".SerializeExceptionSecondService"
        android:enabled="true"
        android:exported="true"
        android:process=":second_remote" >
    </service>

这样,binder 异常 logcat 将如下所示:

在此处输入图像描述

于 2016-08-01T08:24:36.393 回答