29 March 2006
Java Puzzler: Thine Stack Overfloweth
THE PROBLEM:
A buddy of mine chatted me up over IM the other day with the following, seemingly simple problem:
- He has a class that extends the standard Java 1.4 Exception class (BaseException)
- Whenever he catches a thrown
BaseException, and tries to print the stacktrace (viaBaseException.printStackTrace()) he gets ajava.lang.StackOverflowerror. - If he calls
getCause().printStackTrace()everything is cool.
Wierd. “Send me your code” I said. Here is the code:
import java.io.PrintWriter; import java.io.StringWriter; public class BaseException extends Exception { public BaseException() { super(); } public BaseException(String message) { super(message); } public BaseException(Throwable cause) { super(cause); } public BaseException(String message, Throwable cause) { super(message, cause); } public String toString() { StringWriter s = new StringWriter(); printStackTrace(new PrintWriter(s)); return s.toString(); } }
Hmm. Looks reasonably straight forward. I quickly created a simple unit test to verify his results, and sure enough, as soon as the printStackTrace() method called — Blamo! java.lang.StackOverflowError. As in:
public void testPrintStackTrace() { try { throw new BaseException("Yikes!"); } catch (BaseException be) { StringWriter s = new StringWriter(); be.printStackTrace(new PrintWriter(s)); // ka-BLAM! assertNotNull(s.toString()); } }
Well as it turns out the solution really is quite simple, but was not immediately obvious (at least it wasn’t to me.) Do you see it (Don’t cheat!)
THE SOLUTION:
The StackOverflow problem is the give away, it almost always suggests a recursion problem and this case is no Exception (zing!). The problem is that the standard Exception.printStackTrace() calls the toString() method– which in turn has been coded to call printStackTrace()– which in turn calls toString()– etc.
The simple fix was to tweak the toString() implementation. Viola.
Technorati Tags: java, puzzler
Comments are locked.
don says:
mike says:
Excellent post!


BTW, for those that are interested, neither findbugs (mentioned here: http://alterlabs.com/java/better-code-automagic-findbugs/) nor checkstyle identified this issue.