Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ClassNotFoundException on serializable class during activity start

Tags:

android

The Setup

I have an activity that only overrides onCreate(), onResume(), and onSaveInstanceState(). In onSaveInstanceState(), I put in a serializable object:

    @Override 
    public void onSaveInstanceState(Bundle state) {
        super.onSaveInstanceState(state);
        state.putSerializable("obj", myObj); // myObj is of class MyClass               state.putLong("long", longVar);
    }

MyClass was originally an inner class inside the activity class, but for debugging, I even moved it to a separate file:

public class MyClass implements Serializable {
    private static final long serialVersionUID = 0x98ED2F00;
     ....
}

The Steps:

  1. Start the program in the usual way, it runs fine.
  2. Click Home button to go back to the Launcher.
  3. From Eclipse, stop the process from the Device panel
  4. Start the program again from Launcher, this time I get the following:

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.Reports}: java.lang.RuntimeException Parcelable encountered ClassNotFoundException reading a serializable object {name = com.example.MyClass}

    Caused by: java.lang.ClassNotFoundException: com.examp.MyClass in loader dalvik.System.PathClassLoader[.]

Clues and Observations:

  1. The most important clue is: if I don't save myObj in onSaveInstanceState(), then everything is fine. And, putting any primitive types into the Bundle is fine, but not my objects.

  2. The exception is thrown outside of my code, it happened between onCreate() and onResume(). It happened inside Android.

  3. The class name in the error message is correct: com.example.MyClass. Originally it was an inner class inside the activity, but to isolate the problem, I moved it to a separate file, to no avail.

  4. I believe the implementation of Serializable is correct, because it can be serialized to/from a file in other parts of the program.

Does anybody have an idea of any possible cause of this? Much appreciated! (Sorry I can't put detailed code here, because everything is intertwined here and there. I can only isolate as much as possible.)

like image 232
wwyt Avatar asked Mar 09 '11 22:03

wwyt


2 Answers

OK, I think I found a solution to this problem.

It turned out that if the savedInstanceState parameter passed into onCreate() is not null, then one MUST deserialize any objects contained in that Bundle. I don't know why, but this is how I got rid of the problem. Originally my code in onCreate() has the logic that under some conditions, I disregard the savedInstanceState. Now what I do is as long as it's not null, I'll just deserialize everything out, then, based on other conditions, I decide if I use them or not.

So far it runs fine. But I have no idea about:

  1. Why do I have to deserialize them out, and if I don't, exception happens?

  2. What was Android doing to deserialize my things I put in savedInstanceState? I mean, I understand that Android may have put some information for its own use, but why does it come and try to deserialize my things? If it knows it doesn't know how to use them?

like image 75
wwyt Avatar answered Sep 30 '22 08:09

wwyt


I've been fighting this same issue and the way I ended up resolving it was to implement Parceable instead of Serializable in the class I was stashing in the Bundle.

I was able to reliably reproduce the crash by using the DevTools app on the emulator (doesn't seem to work on a real device) and changing the Development Settings > Immediately destroy activities to be checked. Changing my custom class to Parceable and changing to putParcelable in my onSaveInstanceState seemed to fix the problem.

like image 34
swanson Avatar answered Sep 30 '22 06:09

swanson