Find path to offending non-Serializable member variable
java, serialization
Solution
This is a strange question - you're wanting to determine at runtime what you should be doing at compile time. In theory, the path to the object shouldn't matter - you need to find the objects that reference things that aren't serializable to fix your code.
That said, you could write a simple recursive tree crawler using reflection. That said, you might be able to get away with implementing your own ObjectInputStream that logs the objects coming in appropriately. I recommend taking a look at the source for more detail
Problem
In Java, Serialization makes reading and writing objects to streams REALLY easy. For instance, the following code snippet is mostly all it takes to write objects to a stream: ``` ObjectOutputStream oos = ... //Initialize your output stream Object toWrite = ... //Initialize what you want to write here oos.writeObject(toWrite); //Writes the object to the stream oos.flush(); ``` This will work just fine, provided that `toWrite`'s class implements the `Serializable` interface, AND that all of `toWrite`'s non-`transient` member variables are also `Serializable`. In other words, the entire Object hierarchy you are trying to send via the `toWrite` reference must be `Serializable`. Assume that the only problem with this code is that something inside `toWrite` isn't `Serializable`. If the hierarchy isn't completely `Serializable`, the call to `oos.writeObject(toWrite)` throws a `java.io.NotSerializableException`. This is all fine and good, except that the Exception doesn't give you quite everything you need to fix the problem quickly. It will tell you what class couldn't be serialized. Your stack trace might look something like this: ``` java.io.NotSerializableException: some.package.and.ClassIDidntExplicitlyReference at java.io.ObjectOutputStream.writeObject0(Unknown Source) ... at my.package.MyClass.codeThatWroteTheOffendingObject(MyClass.java:###) ``` This sort of points you in the right direction, but in cases that involve deep Object hierarchies referenced by `toWrite`, it's not always clear where the offending class reference came from. Let's say I assign `toWrite` to an instance of `MyClass` and my instance of `MyClass` has a member Object reference called `nonSerializableReference` that has been set to an instance of `ClassIDidntExplicitlyReference`, which is not `Serializable`. I'd like to see something like the following printed out: ``` my.package.MyClass.nonSerializableReference instanceof some.package.and.ClassIDidntExplicitlyReference ``` I know this problem probably doesn't have a quick solution, and will likely involve using Reflections. Has anyone here on SO done this before and if so, would you mind sharing your insight? Answer I ended up using Reflection's `Field` and `Modifier` class to find the path. Unfortunately, I can't share my code (against company policy), but I can show you my output. Class A holds an instance of B, B holds an instance of C, and C holds an instance of D. All are `Serializable` except for D. I ended up using Depth-First-Search to find the path: ``` A.b -> B.c -> C.d instanceof class D ``` If I make `C.d` transient, the search yields no results. Pretty cool!