NullPointerException (etc.) From Parcel.readException

Exceptions that look like this are confused:

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) 

I found several related questions for this, but none of them answered the question "how do you debug this." So I am doing this question / answer.

Looking at the android source here and here you will see that it could be throwing any of them (the NullPointerException exception is what I had):

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

But what causes them?

+7
android parcel
source share
2 answers

What happens here is that readException() checks the IPC byte stream for a header that says an exception has occurred; if he finds one, he will throw a new exception of this type with the same message, but will not skip the original stack trace. (He really knows only a few types of exceptions; everything else is translated into the RuntimeException database.)

So where did the original exception come from? Well, somewhere in the throes of the actual implementation of YourClass.yourMethod() - not in any of the possible or IPC codes. So go there, wrap the whole method in try / catch and register everything you caught.

(Or set a breakpoint there if you have remote points of remote processes.)

+16
source share

I think the Android MUST provide additional information about deleted middleware exceptions

so I modify Parcel.java to wrap more information about deleted middleware exceptions

 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 defination:

 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 } }; } 

fragment of AndroidManifest.xml:

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

thus, the middleware exception log code will look like this:

enter image description here

0
source share

All Articles