I wrote a little test to see how many try/throw/catch could be done in a loop. I was surprised to find that the time spent is proportional to the stack depth at which the exception is thrown, even if there are no frames between the try{} and throw. This makes sense, because the Throwable frames array is being populated at the point of the throw, up to the limit. Which leads to: yes, this option DOES have a performance impact (in addition to logging, as noted by Rogue), but only when the stack depth at the point of throw is higher than XX:MaxJavaStackTraceDepth.
Test code:
public class Test1 {
static int DEPTH = 10;
static void test(int depth) {
if (depth < DEPTH) {
// Wait until we get to the desired depth
test(depth+1);
} else {
int ITER = 1000000 / DEPTH;
long start = System.currentTimeMillis();
for (int i = 0; i < ITER; i++) {
try {
throw new RuntimeException();
} catch (Exception ex) {}
}
long end = System.currentTimeMillis();
System.out.println("DEPTH=" + DEPTH + ": throws/sec=" + ITER / ((end - start) * 0.001f));
}
}
public static void main(String[] args) throws Exception {
for (DEPTH = 1; DEPTH <= 10000; DEPTH *= 2) {
test(0);
}
}
}
Run with default
$ java -jar target/*shad*jar
DEPTH=1: throws/sec=1182033.1
DEPTH=2: throws/sec=1184834.1
DEPTH=4: throws/sec=1068376.0
DEPTH=8: throws/sec=833333.3
DEPTH=16: throws/sec=578703.7
DEPTH=32: throws/sec=336021.5
DEPTH=64: throws/sec=195312.48
DEPTH=128: throws/sec=91905.88
DEPTH=256: throws/sec=48824.996
DEPTH=512: throws/sec=25697.367
DEPTH=1024: throws/sec=13369.862
DEPTH=2048: throws/sec=12842.1045
DEPTH=4096: throws/sec=12199.999
DEPTH=8192: throws/sec=12199.999
Run with larger stack trace:
$java -XX:MaxJavaStackTraceDepth=1000000 -jar target/*shad*jar
DEPTH=1: throws/sec=1166861.1
DEPTH=2: throws/sec=1157407.4
DEPTH=4: throws/sec=1050420.1
DEPTH=8: throws/sec=816993.4
DEPTH=16: throws/sec=578703.7
DEPTH=32: throws/sec=322164.94
DEPTH=64: throws/sec=190548.78
DEPTH=128: throws/sec=87775.28
DEPTH=256: throws/sec=50076.92
DEPTH=512: throws/sec=26039.998
DEPTH=1024: throws/sec=13189.189
DEPTH=2048: throws/sec=6777.7773
DEPTH=4096: throws/sec=3388.8887
DEPTH=8192: throws/sec=1718.3098
So you can see, with the default trace limit of 1024, the performance levels off around 12K/sec above the limit of 1024. But when you unlimit the trace size, the performance continues to decline.
Thanks to Rogue for suggesting the logging impact.
Side thought: as often stated, never use exceptions for normal flow control! Because you have no control over performance, depending on the stack depth when your code is called.