Saturday, December 1, 2012

Gotcha: Java Concatenation

The Problem

Recently one of my co-workers had an issue with a website written in JSP. Every time he went to a page, a Servlet Filter was failing with an error that the Java class "StringBuilder" was not found. I've added this Servlet Filter in the application recently and this worked fine on other machines and in our Test Servers, but failed on this one machine. Also, we use Java 1.4 and there is no way we could be using Stringbuilder which was only introduced in Java 1.5.  (Java 1.4 has only StringBuffer. See here for a discussion on the two).

(I know we are using older technology - we use Sybase EA Server 5.5, which forces us to stick with Java 1.4, but go with me on this.)

Java Strings and Java Compiler

I set to find our why it was complaining about something we don't use. I looked at the class file generated. It had "StringBuilder". Then it hit me. We use a lot of String Concatenation in our code and we use String concatenation using plus sign (+). This seemingly innocuous usage caused it and the error has to do with Compiler Optimization.

Java Strings are immutable, meaning they cannot be changed at run time. Each time we concatenate Strings, we are essentially creating newer and newer Strings.

So, str1 + str2 + str3 is essentially equivalent to

res1 = str1 + str2

res2 = res1 + str3

But Compiler may take a different approach to optimize concatenation using StringBuffer or StringBuilder (See here). So the above, concatenation can be rewritten (by compiler) as,

StringBuilder(str1).append(str2).append(str3);

So this is what happened in our case. Some concatenation got turned into StringBuilder by the Compiler and hence the error. Wasn't that supposed to read StringBuffer (because it's supposed to be Java 1.4)? Well that was because of another mistake. When he set up Eclipse our friend used a newer version than the one I recommended which defaulted to Java 1.6 compiler which caused the optimizer to produce > 1.5 code!! Hence the error on StringBuilder. But the error showed up in the first place because of the Compiler Optimization! If the compiler used the String.Concatenate in the first place, we would not have seen this error!!.

And Compiler may sometimes choose to do just that, use String.Concatenate as shown in preciseJava.com. Also, such Compiler optimization may not be always good. See this interesting blog about various possibilities of concatenations.

Oh yeah, We overrode the workspace settings in Eclipse to use 1.4 compiler for the project and all is well now.

Reference Links

  1. http://chaoticjava.com/posts/stringbuilder-vs-string/

  2. http://javamoods.blogspot.com/2010/02/optimization-dont-do-it-compiler-will.html

  3. http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&ved=0CF4QFjAE&url=http%3A%2F%2Fciteseerx.ist.psu.edu%2Fviewdoc%2Fdownload%3Fdoi%3D10.1.1.122.5641%26rep%3Drep1%26type%3Dpdf&ei=LIK6UMCwBMWUjAK4_4HIBw&usg=AFQjCNFo6trLwU4wlxgrTNFBa1tGb1p9Cg&sig2=qHQIg8S0qI-CXdJ6EOaa8w

  4. http://www.precisejava.com/javaperf/j2se/StringAndStringBuffer.htm

  5. http://code-thrill.blogspot.com/2012/08/stringbuilder-optimizations-demystified.html

No comments :

Post a Comment

I will be happy to hear your comments or suggestions about this post or this site in general.