Wednesday, August 25, 2010

System.currentTimeMillis();

I ran across an interesting issue today involving JVM internals, and how they behave differently based on the host OS.

The issue was with the following code snippet:

MyEntity a = new MyEntity();
a.setUid("foo" + System.currentTimeMillis());
a.setName("my entity");
entityService.save(a);

This was part of some object creation code I was using in a unit test, which ran successfully every time on my macbook but was failing on other's windows machines. When I found out the reason behind this, I was definitely surprised.

Believe it or not, it is more or less a known issue that the resolution of currentTimeMillis() on windows machines hovers around 10-15ms (linux and mac have a resolution of around 1ms). This was causing duplicate foreign key violations to occur.

So, as a general rule of thumb, it is a bad idea to rely on currentTimeMillis() to have a millisecond-resolution on windows, especially if you are using it to generate unique things like file names or db IDs. Looks like System.nanoTime() might tick faster.

Here are some links I found on StackOverflow about this:

On Windows, you'll more or less be limited to 10 ms resolution at best. Here's a bit from the Inside Windows NT High Resolution Timers article from TechNet:

Windows NT bases all of its timer support off of one system clock interrupt, which by default runs at a 10 millisecond granularity. This is therefore the resolution of standard Windows timers.

In my experience, using System.currentTimeMillis method gives about 15-16 ms resolution on Windows. Getting better time than the operating system timer will probably require more exotic methods.

Here's the StackOverflow question which helped me solve this issue:
http://stackoverflow.com/questions/351565/system-currenttimemillis-vs-system-nanotime

At the end of the day, I decided it was simpler for my test to use a static synchronized counter variable rather than depending upon currentTimeMillis() for generating my UIDs. Another possible solution could be to use UUID.randomUUID().toString().

Wednesday, August 11, 2010

Fixing ClassNotFoundExceptions when working with Eclipse WTP, Maven, Tomcat

Lately, I've been struggling off and on with ClassNotFoundExceptions when starting tomcat from within Eclipse (Springsource Tool Suite, to be exact). My projects are all dependency-managed by the Maven m2eclipse plugin (side note: its really important to install the m2eclipse WTP add-on, found here: http://m2eclipse.sonatype.org/sites/m2e-extras so that the web dependencies are all configured correctly).

Anyways, I would tend to encounter this error after restarting Eclipse. When I would investigate, by looking into the [tomcat_home]/wtpwebapps/[app]/WEB-INF/lib folder, it would of course be empty (hence, class not found). I would always flail about aimlessly for hours until it would magically start working again.

I have in the past week discovered a new trick, which has worked *both* times I've tried it: when I got the class not found error, I stopped tomcat, right clicked on my project in the Package Explorer, and clicked Maven -> Update Dependencies. For whatever reason, this caused WTP to publish the dependent jars into WEB-INF/lib, and everything worked again. :-)

Hope that helps save some debugging hours for some!