Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find source of crashes of type java.lang.RuntimeException: Parcel android.os.Parcel@####: Unmarshalling unknown type code XXXX at offset YYY

Our crash reporting system is logging crashes of this type:

Caused by java.lang.RuntimeException: Parcel android.os.Parcel@8bf0d1f: Unmarshalling unknown type code 6881391 at offset 356
   at android.os.Parcel.readValue(Parcel.java:2779)
   at android.os.Parcel.readSparseArrayInternal(Parcel.java:3148)
   at android.os.Parcel.readSparseArray(Parcel.java:2362)
   at android.os.Parcel.readValue(Parcel.java:2757)
   at android.os.Parcel.readArrayMapInternal(Parcel.java:3067)
   at android.os.BaseBundle.unparcel(BaseBundle.java:257)
   at android.os.Bundle.getSparseParcelableArray(Bundle.java:958)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1329)
   at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
   at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3244)
   at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:3194)
   at android.support.v4.app.Fragment.restoreChildFragmentState(Fragment.java:1444)
   at android.support.v4.app.Fragment.onCreate(Fragment.java:1415)
   at com.payments.base.BaseFragment.onCreate(BaseFragment.java:68)
   at com.payments.app.fragments.TopLevelFragment.onCreate(TopLevelFragment.java:422)
   at android.support.v4.app.Fragment.performCreate(Fragment.java:2331)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1386)
   at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
   at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
   at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3244)
   at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:3194)
   at android.support.v4.app.Fragment.restoreChildFragmentState(Fragment.java:1444)
   at android.support.v4.app.Fragment.onCreate(Fragment.java:1415)

What I know: This occurs when app is restored from background, and onCreate is called. Our app is a Single-Activity app, with all UI managed by fragments. This crash is infrequent, and very hard to reproduced in our dev environment.

Also - I don't believe the cause is some parcelable object we created, rather Android component reloading, but not sure.

What I'd like to know: how to analyze these stacktraces to pinpoint the cause? how to make use of the little data given?

Note that the stacktrace hardly points to any particular line in our app, and where it does - only to the onCreate methods of our activity and fragments base classes

like image 262
Mardann Avatar asked Mar 14 '19 09:03

Mardann


2 Answers

I just learned that you can keep your test device from keeping activities. There is an option in the Developer options, section "Apps" that, when switched on, destroys activities everytime they user leaves them.

After turning this option on, I was able to reproduce the error by just closing and reopening my app. As you said, it's an error in the onCreate() method. In my case, the reason is a ClassNotFoundException when unmarshalling a custom Parcelable from my saved instance state. This might not be a solution to your problem but at least might help you to reproduce and pin down the error. Happy hunting!

like image 111
Richard R Avatar answered Sep 30 '22 12:09

Richard R


In my experience, an error such as this is less about what is happening when the error occurs, and more about what happened earlier in your app. Specifically when the app went into the background.

But starting with what the stack trace is revealing. TopLevelFragment is being restored from previous state. During this restore, TopLevelFragment's child fragments are being restored. While restoring the child fragments, the saved fragment state of one of the fragment's attempts to unparcel itself when getSparseParcelableArray() is called on Bundle to retrieve the fragment's saved view state. This happens in FragmentManager.java, line 1329. There's something about the saved fragment state that Parcel doesn't know what to do with as it's unmarshaling itself.

To narrow down which child fragment of TopLevelFragment you should focus on, I would put a breakpoint on line 1329 of FragmentManager.java and inspect the type Fragment f is. Keep in mind, you may have multiple child fragments getting restored, so you want to see which fragment can't get past line 1329.

But of course you have force this restore logic to happen consistently. If you simply send your app to the background and bring it back to the foreground, this probably won't happen. So you can do as Richard R suggests and use the "Don't keep activities" developer option to force Android to destroy and restore activities.

Once you narrow down which fragment is the problem, you need to go back earlier in your app and take a closer look at the types of data you are putting into the save state in Fragment.onSaveInstanceState(). Hopefully this points you in the right direction.

If this is a proguard problem, you should see the error disappear if you disable minification. And if that's the case, you may need a proguard rule or a @Keep annotation on one of your custom Parcelable types. If the error happens with and without minification, it's probably not proguard related.

like image 39
Greg Moens Avatar answered Sep 30 '22 10:09

Greg Moens