Monday, April 23, 2018

The Curious Case of tracing Java Serialization NotSerializableException

I say curious, because Java Serialization has been around for a very long time, and yet I could not find any tools to help track down exactly where the NotSerializableExceptions were coming from.

Yes, of course, the stack trace tells you which class has caused the offence, but even in a mildly complex object graph, the source of the error can be tough to find.

So in the end, I wrote SerializationTracer, which walks through the object graph being serialised and identifies objects which fail or succeed in serialising.  Null fields and empty collections are assessed with some static analysis.

The output looks like this:

UIScope -> SerializationResult(outcome=FAIL, info=java.io.NotSerializableException: com.google.inject.Key)
UIScope.cache -> SerializationResult(outcome=FAIL, info=java.io.NotSerializableException: com.google.inject.Key)
UIScope.cache.comparator -> SerializationResult(outcome=NULL_FAILED_STATIC_ANALYSIS, info=Comparator is NOT Serializable. ? super K is NOT Serializable.)

The first part of each line points to the exact field causing the problem, using an object 'path' - pretty trivial in the example above, but of course that could extend a long way down into a deep object graph.
It was designed with testing in mind, but we are now thinking of putting it into 'production' - that is, trapping a failed session serialisation, and using SerializationTracer to give us a more coherent understanding of the source of failure.