NullPointerException (etc) de Parcel.readException

Las excepciones que se parecen a esto son confusas:

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) 

Encontré un montón de preguntas relacionadas para esto, pero ninguna con la respuesta a "¿cómo depurar esto". Así que estoy haciendo esta pregunta / respuesta.

Al mirar la fuente de Android aquí y aquí usted verá que puede estar lanzando cualquiera de estos (el NullPointerException es justo lo que tenía):

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

Pero, ¿qué causa esto?

Lo que está pasando aquí es que readException() está comprobando el flujo de bytes IPC para un encabezado que dice que se produjo una excepción; Si encuentra uno, entonces lanza una nueva excepción de ese tipo, con el mismo mensaje, pero falta el rastreo de pila original. (Sólo conoce algunos tipos de excepciones, todo lo demás se traduce en una base RuntimeException .)

Entonces, ¿de dónde viene la excepción original? Bueno, en algún lugar en las entrañas de la aplicación real de YourClass.yourMethod() – no en cualquiera de los parcelable o código IPC. Así que ir allí, envolver todo el método en un try / catch, y registrar lo que capturó.

(O establecer un punto de interrupción allí si tienes puntos de interrupción de proceso remotos trabajando.)

Creo que android DEBE proporcionar más información de excepción remota de carpeta

Así que modifico Parcel.java para envolver más información de excepción remota del encuadernador

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

Definición de 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 } }; } 

Fragmento de AndroidManifest.xml:

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

De esta manera, el logcat de enlace se verá como el siguiente:

Introduzca aquí la descripción de la imagen

  • Problema de Bundle.putExtra con android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.