http://guava-libraries.googlecode.com/svn/trunk/src/com/google/common/base/Preconditions.java
/*
* All recent hotspots (as of 2009) *really* like to have the
* natural code
*
* if (guardExpression) {
* throw new BadException(messageExpression);
* }
*
* refactored so that messageExpression is moved to a separate
* String-returning method.
*
* if (guardExpression) {
* throw new BadException(badMsg(...));
* }
*
* The alternative natural refactorings into void or
* Exception-returning methods are much slower. This is a big deal
* - we're talking factors of 2-8 in microbenchmarks, not just
* 10-20%. (This is a hotspot optimizer bug, which should be fixed,
* but that's a separate, big project).
*
* The coding pattern above is heavily used in java.util, e.g. in
* ArrayList. There is a RangeCheckMicroBenchmark in the JDK that
* was used to test this.
*
* But the methods in this class want to throw different exceptions,
* depending on the args, so it appears that this pattern is not
* directly applicable. But we can use the ridiculous, devious
* trick of throwing an exception in the middle of the construction
* of another exception. Hotspot is fine with that.
*/
Could someone provide more information?
I commonly write my exceptions like:
if (guardExpression) {
String message = ....; // String concatenation here.
throw new BadException(message);
}
Is this saying that I should move the generation of message into a
separate method?
If 99.99% of the time you don't except exceptions, then I guess this
isn't that large of an issue?
On a side note, with Scala and the ability to generate a thunk or
by-name value, this then fits the pattern:
def myAssert(assumption: Boolean, message: => String): Unit =
{
if (!assumption)
throw new java.lang.AssertionError(message)
}
}
But looking at the bytecode, this ends up calling
java.lang.AssertionError's constructor that takes a java.lang.Object,
not the one that takes a String, which looks like a Scala compiler issue.
Blair