Tuesday, July 6, 2010

The tale of a Calendar... a Date... and a Object reference bug..

To set the scene, there is a software release 4 days away and everyone is in mid-pre-release-panic... There is one of those nasty bug's only happens sometimes, and was missed by testing until 2 hours before final signoff, and is "absolutely necessary" for the release.

I rush off go through the date calculations done by our system, adding and changing To and From dates into a sequence depending on some items, not overly complicated but just enough to have quite a few Calendar and Date objects flying around.

So I figure it has to be an object reference being used of one the Date objects, because 2 of the dates set are to the same value. This obviously only happens on the actual deployment and my unit tests pass, and debugs print out the right values..

First thing I do is look for shared Date objects (all the Date objects get created via Calendars or set back to the Calendar like below:



The shared Date objects are then used on a internal Period class that has From and To dates and some convenience methods that is used all around our system and it was those date values that were incorrect.

So I think... easy.. I'll just add ".clone()" the Date because it must be their object references.... I put in 2x .clone() compile, deploy ... test... fail... 2 Dates still the same.

Go back to the code, get a second pair of eyes, a work colleague. Together we slap together this completely immutable class, that makes the calculations less complicated and ensures that there can't be any object reference sharing between that dates and the calendars or anything, and at the same time create a new Period object to hold these new dates from our new class that we made sure that could not be messed with by reference.

build, deploy ... test ... works like a charm.. notify the testers, they sign off ... all is good.

A hour or so later, the same work colleague pops me an IM on MSN Messenger... says that this could happen somewhere else... we get the code... at roughly the same time we both happen to go into Calendar.getTime() source code and to our surprise (and amusement) we discover a little gem... both can't believe that we had not actually seen it before..

Calendar source code below:



The standard java Calendar had ensured a long time ago that you would not have this object reference scenario and that it is safe by using the "TimeInMillis". So we had wasted a good 30 minutes of our lives, when the only issue was our own Period object that was the bad reference.

So I guess the point of this is....

1. Using the Calendar.getTime() and setTime() is safe and won't let you pollute object references.. and...
2. I had a similar discovery with Spring a little while back (...) So it is fair to say if you have the source code of classes you are using, its probably an excellent idea to have a look at it from time to time.

2 comments:

  1. Instances of java.util.Date should be used as immutable objects only. Why in the world would you have shared Date instances that you would modify?

    ReplyDelete
  2. You are right, I re-read how I described the code, and it did sort of come out wrong... I was only using the Calendars to modify, and by "shared" dates I meant the dates that were contained on the Period object on a DTO used to initiate the calculations and contain the result of manipulations.

    ReplyDelete

Popular Posts

Followers