If I run the following test, it fails:
public class CrazyExceptions {
private Exception exception;
@Before
public void setUp(){
exception = new Exception();
}
@Test
public void stackTraceMentionsTheLocationWhereTheExceptionWasThrown(){
String thisMethod = new Exception().getStackTrace()[0].getMethodName();
try {
throw exception;
}
catch(Exception e) {
assertEquals(thisMethod, e.getStackTrace()[0].getMethodName());
}
}
}
With the following error:
Expected :stackTraceMentionsTheLocationWhereTheExceptionWasThrown
Actual :setUp
The stack trace is just flat out lying.
Why isn't the stack trace rewritten when the exception is thrown? I am not a Java dev, and maybe I'm missing something here.
The stack trace is created when the exception is instantiated, not when it is thrown. This is specified behaviour of the Java Language Specification
20.22.1 public Throwable()
This constructor initializes a newly created Throwable object with null as
its error message string. Also, the method fillInStackTrace (§20.22.5) is
called for this object.
....
20.22.5 public Throwable fillInStackTrace()
This method records within this Throwable object information about the
current state of the stack frames for the current thread.
I don't know why they did it that way, but if the specification defines it like that, it is at least consistent on all the various Java VMs.
However, you can refresh it by calling exception.fillInStackTrace()
manually.
Also note that you should use Thread.currentThread().getStackTrace()
instead of using new Exception().getStackTrace()
(bad style).