Why can I "fake" the stack trace of an exception in Java? - java

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).

The stacktrace of the exception is filled in at creation time of the exception. Otherwise it would be impossible to catch an exception, handle it and rethrow it. The original stacktrace would get lost.
If you want to force this you have to call exception.fillInStackTrace() explicitly.

Because you didn't ask that that stack trace be rewritten. It was set when you created it in the setUp method, and you never did anything to alter it.
The Exception class doesn't give you any opportunity to set the method name; it's immutable. So there's no way that I know of where you could re-set the method name, unless you wanted to resort to something heinous like reflection.
Your #Test annotation doesn't tell me if you're using JUnit or TestNG, because I can't see the static import, but in either case you can run a test to see if a particular exception is thrown by using the "expected" member in the #Test annotation.

You wouldn't want throwing an exception to alter the stack track or you couldn't re-throw an exception safely.
public void throwsException() {
throw new RuntimeException();
}
public void logsException() {
try {
throwsException();
} catch (RuntimeException e) {
e.printStrackTrace();
throw e; // doesn't alter the exception.
}
}
#Test
public void youCanSeeTheCauseOfAnException(){
try {
logsException();
} catch(Exception e) {
e.printStrackTrace(); // shows you the case of the exception, not where it was last re-thrown.
}
}

The stack trace in the exception corresponds to the "new" operation, nothing else.

I think the assumption is that you won't be instantiating an exception unless you are in the process of throwing it, so why pay the price to get the stack trace twice?
It would be difficult to recreate the stack trace while throwing it, as that is just sending the object out.
The exception should be fully setup before the throw, so part of the instantiation is to get the stack trace.
UPDATE:
You can call fillInStackTrace() to resolve this.

Related

test exception is not thrown

I'm creating an integration test:
#RunWith(CdiRunner.class)
#AdditionalClasses({FollowUpActivityRepository.class, SettingsPropertiesProducer.class})
public class FollowUpActivityFeaturesTest {
#Inject protected FollowUpActivityService fuaService;
#Test
public void DigitalInputTOFollowUpActivityFIELDS()
{
FollowUpActivityDTO dto = new FollowUpActivityDTO();
dto.setId("id");
dto.setTimestamp(Date.from(Instant.now()));
dto.setDueTimestamp(Date.from(Instant.now()));
dto.setClosingTimestamp(Date.from(Instant.now()));
dto.setMatter("matter");
dto.setComment("comment");
this.fuaService.createOrUpdate(dto);
}
}
createOrUpdate is like:
public void createOrUpdate(FollowUpActivityDTO dto) throws RepositorySystemException
So, I need to check this exception is NOT thrown.
I'd like to do it elegantly.
Actually, I'm using junit 4.12 and hamcrest 2.0.0.0.
Any ideas?
Example
In .NET, I'm using NSubstitute in order to get that:
this.apiClient.Invoking(c => c.GrantAuthorization()).ShouldNotThrow();
Edit after you reversed the meaning of the question:
If you want your test to fail if an Exception is thrown, you have nothing more to do than just declare an Exception in the throws part of the test method signature (this is not mandatory if the Exception thrown is some kind of RuntimeException, but yours obviously isn't):
public void DigitalInputTOFollowUpActivityFIELDS() throws Exception
No need to specify any kind of Exception. Anyway, any jUnit test will fail as soon as an unhandled Exception is thrown (which is the behavior you're expecting).
From this blog:
Test methods that declare that they throw one particular type of
exception are brittle because they must be changed whenever the method
under test changes.
Old answer:
Just write your test annotation like this:
#Test(expected=RepositorySystemException.class)
This way, the test method will succeed as soon as this exception is thrown.
See javadoc.
Edit after your comment:
To validate the test against any Exception, just:
#Test(expected=Exception.class)
But as B. Dalton suggested, that seems kind of dangerous, as this test would then pass on any Exception, no matter if it's the one you're expecting or any other.
For the sake of completeness, you can also do something like this (based on this answer):
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void DigitalInputTOFollowUpActivityFIELDS()
{
FollowUpActivityDTO dto = new FollowUpActivityDTO();
dto.setId("id");
dto.setTimestamp(Date.from(Instant.now()));
dto.setDueTimestamp(Date.from(Instant.now()));
dto.setClosingTimestamp(Date.from(Instant.now()));
dto.setMatter("matter");
dto.setComment("comment");
thrown.expect(Exception.class);
thrown.expectMessage("something you can check"); // if needed
this.fuaService.createOrUpdate(dto);
}
This way, createOrUpdate will still be able to validate the test by throwing any kind of Exception, but at least the rest of the method won't.
See javadoc for ExpectedException.
Or, of course, the good old solution:
try {
this.fuaService.createOrUpdate(dto);
fail("this should throw an exception");
} catch (RepositorySystemException e){
// pass
} catch (Exception e){
// pass
}
This is less elegant, but allows you to tweak the exception handling as you need.

Unhandled exception type Exception

This is a simplified class that describes my problem:
public class Main {
enum Test{
First(method()){ // Unhandled exception type Exception
// ...
};
Test(Object obj){
//...
}
}
static Object method() throws Exception{
// ...
if (someCondition){
throw new Exception();
}
}
}
Above someCondition depends on device and some situations and I can not decide in about it now, also as you can see, I do not want to catch Exception in method.
Yes. It is a compilation error.
No. There is no special syntax to deal with this.
I do not want to catch Exception in method.
Unfortunately if you throw a checked exception, it has to be caught further up the call stack. That is a fundamental design principal for the Java language, and one that the compiler enforces strictly.
In this, case there is no way to catch the checked exception. Hence, if you are going to call a method in enum constant parameter (as per your code), the method cannot throw a checked exception1.
Here is a possible workaround, though this is probably a bad idea:
public class Main {
enum Test{
First(methodCatchingException()){
// ...
};
Test(Object obj){
//...
}
}
static Object method() throws Exception{
// ...
if (someCondition){
throw new Exception();
}
}
static Object methodCatchingException() {
try {
return method();
} catch (Exception ex) {
throw new SomeRuntimeException("the sky is falling!", ex);
}
}
}
Another way to look at this problem is to ask yourself what should happen with the exception if the compiler let you write that ... and an exception was thrown? Where would it go?
You can't catch it ... because the enum initialization is like a static initialization.
If the Java runtime completely ignored the thrown exception, that would be really bad.
If the Java runtime crashed, then the model of checked exceptions is broken.
So, what this is saying to me is that the Java language design is right, the Java compiler is right ... and the real problem here is in your application design:
You should not be propagating a checked exception here. If an exception occurs in this context it is categorically NOT a recoverable error.
Maybe it is inadvisable to use an enum for this ... because of the potential for non-recoverable initialization errors.
(Note that if this method call terminates due to an unchecked exception, it will turn it into an ExceptionInInitializerError. In addition, the JVM will mark the enum class as uninitializable, and will throw an NoClassDefFoundError if your application attempts to use it; e.g. via Class.forName(...).)
I assume that Exception is used here for illustration purposes. It is a bad thing to declare methods as throws Exception or to throw new Exception(...)
1 - I had a look at the JLS for something to back this up. As far as I can tell, the spec does not mention this situation. I'd have expected to see it listed in JLS 11.2.3. However, it is clear that a compiler cannot allow a checked exception to propagate at that point as it would "break" the model of how checked exceptions work.
I don't think you want to be throwing a checked exception here (which is what Exception is). The reason: you're invoking the call of method inside of the constructor of Test. There's really not a clean way to deal with it.
While the obvious choice here is to switch to RuntimeException, I want you to reconsider throwing the exception in the first place. Since your enum will only ever have First declared in it, does it really make sense for it to throw an exception when it's being instantiated? Personally, I don't think it does; whatever dangerous operation it's doing should be deferred until you want to invoke it, and then would you want to throw your exception.

java throwing exception without catching it?

Is it possible to throw an exception without catching it?
Example
public void foo() throws SomeException{
// ....
if (somethingCatestrophic) throw new SomeException();
// ....
}
Now I want to call foo, but don't want to catch any errors, as the exceptions should never been thrown at runtime (unless there's a bug)
Unless it is something you are planning for and recovering from locally, it is probably best in this case to use an unchecked exception, e.g., a RuntimeException derivative.
Why don't you catch it inside the method?
Simply use try catch block and go on, if the exception is insignificant and doesn't influence any behaviour of your program.
You can avoid catching an exception, but if there is an exception thrown and you don't catch it your program will cease execution (crash).
There is no way to ignore an exception. If your app doesn't need to do anything in response to a given exception, then you would simply catch it, and then do nothing.
try {
...some code that throws an exception...
} catch (SomeException ex) {
// do nothing
}
NOTE: This is often considered bad style, however, and people may tell you so. The often-cited reason is that, even if you're not going to do anything with the exception, that in most cases you should at least log it somewhere, notify the user, or take some other appropriate action depending on what you app is doing, and what caused the exception in the first place. If you're not sure why an exception is being thrown (maybe it's a bug you haven't solved yet), then generally you should at least log it so you can figure it out later.
If SomeException is a checked exception, the method that calls foo() will either have to catch that exception and deal with it or also be declared to throw SomeException or a parent of it.
If SomeException is a runtime exception, then methods that call it will not need to catch it.
There is a trick, You can play with generics.
/**
* A java syntax glitch to throw any throwable without the need to catch it.
*
* #param throwable to be ignite
* #param <T> the type of the throwable to trick the compiler that it's the one thrown
* #throws T exactly the given throwable
*/
public static <T extends Throwable> void ignite(Throwable throwable) throws T {
Objects.requireNonNull(throwable, "throwable");
throw (T) throwable;
}
This test should pass
#Test(expected = IOException.class)
public void ignite() {
ignite(new IOException());
}

relax exception catch necessity

Is there a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions? Maybe compiler flags?
I know the reason why the catching is promoted, but want to do simple and straight tools that enforce their requirements. So if something can went wrong I don't like to catch up but exit the application, crashing with a meaningful exception. Usually this ends up like:
try {
connection.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
which introduces 4 lines of code mess, and introduces the wrapping RuntimeException mess on error output. Sometimes it even motivate people to wrap large try ... catch (Throwable ..) blocks around anything, which is the likely cause for our beloved 'Unknown error occured' alert boxes...
you can use throws keyword with method prototype to avoid try-catch block. which eventually throws the exception to JVM's Default Exception handler which halts the application if no catch block's are specified in your code to handle the exception raised.
Crashing the application at the first sight of an exception is very bad practice. Especially when some work is unsaved and the application is using some resources that needs to be freed and cleaned before the application terminates execution. Some very popular software used to do that... and instead of "fixing" the issue, they introduced a data recoverability features on application restart. However the trick, this is not good software engineering.
At the very least, your application should not crash on the first exception/error encountered, but recover with a meaningful message. It is being lazy to just wrap everything in a RuntimeException (or even Throwable) and, especially, not do anything with it.
Java does not support flags of any kind because there are 1) a workaround, and 2) better ways to handle this situation. For example :
1. Handle the exception in the calling method
You can add the throws keyword in your method declaration, up to your static public void main method, which, if not handling the exception, will eventually crash the application with a stacktrace.
class Foo {
public void someMethod(....) throws IllegalArgumentException, IOException {
...
}
static public void main(String...args) throws Throwable {
new Foo().someMethod();
}
}
This method does not offer any means of recoverability and will probably make your user unhappy (with a big meaningless stachtrace if they ran the application from a console, or just nothing at all if they launched it from a shortcut or GUI). Also, if you have some acquired resources, you will not be able to clean them when an exception occurs. At the very least, your main should catch (Throwable e) and output something before throwing the exception above. Something like :
class Foo {
public void someMethod(....) throws IllegalArgumentException, IOException {
...
}
static public void main(String...args) {
try {
new Foo().someMethod();
} catch (...) {
// output or log exception here and, optionally, cleanup and exit
}
}
}
** EDIT **
Consider this scenario : a program is initializing some resource for processing some data, then some runtime exception (or error) occurs during processing, the application crash, but the resources are not released or freed. In Java, however, one could do this
public E doSomething() throws RuntimeException {
// declare a bunch of resources
try {
// process resources with unchecked exceptions
} finally {
// free resources
}
// return some result
}
and cleanly exit the method on error or on success, perhaps even logging the runtime error for "posterity".
2. Log the error and return some meaningful value
Logging is a very good practice. You can show your user some message telling them that the operation could not be executed without crashing the whole thing, and giving you some traces of what and where the user were doing. A simplistic logging system could be :
class Foo {
static private final Logger LOG = Logger.getLogger(Foo.class.getName());
public boolean doSomethingImpl(...) {
boolean result = true;
try {
...
} catch (SomeException e) {
LOG.log(Level.SEVERE, "meaningful message why method could not do something!", e);
result = false;
}
return result;
}
public void doSomething() {
if (!doSomethingImpl(...)) {
// handle failure here
}
}
}
By default, the Logger will output everything to the err output stream, but you can add your own handlers :
// loggers are singletons, so you can retrieve any logger at anytime from
// anywhere, as long as you know the logger's name
Logger logger = Logger.getLogger(Foo.class.getName());
logger.setUseParentHandlers(false); // disable output to err
logger.addHandler(new MyHandler()); // MyHandler extends java.util.logging.Handler
Java already ships with some default logging handlers, one of which writes to file.
etc.
Is there a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions?
For a checked exception, you can chose between catching the exception and declaring it in the method header as thrown.
Maybe compiler flags?
No. There are no compiler flags to relax this. It is a fundamental part of the language design. Relaxing the checked exception rules via a compiler switch would cause serious library interoperability problems.
I don't think that there's any way around this for the JVM. Your best bet is to have your methods re-throw the exception, which gets rid of the "mess" in your code, and then have your main program throw Exception. This should propagate the error up to the top of your program.
Keep in mind, however, that the place where the exception actually happens is a much better place to let the user know what happened (i.e., exactly what it was doing when this particular IOException happened). You'll lose this resolution if all errors are simply propagated up to the top level.
You do have the ability to throw your exceptions up a level. Here's an example
public class Foo {
public Foo() {
super();
}
public void disconnect(connection) throws IOException {
connection.close();
}
}
Use "Throws" to avoid the error..but it will not be good programimg practice

How do I throw an Exception from the caller's scope?

I'd like to create a routine that does some logging, takes some other actions, and then throws an Exception. I'd like this routine to be called from many different locations. However, creating Exceptions in this routine means they will have this routine in their stack trace. I would rather the stack trace not report this utility routine. Is there a way to do this without creating the Exception in the caller and passing it to the utility routine?
public static void die(String message) throws MyException {
log(message);
...
throw new MyException();
}
For programmers who are Perl/Java bilingual: how do I carp in Java?
You can set the stack trace of any exception you want to throw:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CarpTest {
public static void main(String[] args) {
new CarpTest().run();
}
public void run() {
methodThatCarps();
}
private void methodThatCarps() {
carp("Message");
}
private void carp(String message) {
RuntimeException e = new RuntimeException(message);
e.fillInStackTrace();
List<StackTraceElement> stack = new ArrayList<StackTraceElement>(Arrays.asList(e.getStackTrace()));
stack.remove(0);
e.setStackTrace(stack.toArray(new StackTraceElement[stack.size()]));
throw e;
}
}
This will print the following stacktrace at runtime:
Exception in thread "main" java.lang.RuntimeException: Message
at CarpTest.methodThatCarps(CarpTest.java:18)
at CarpTest.run(CarpTest.java:14)
at CarpTest.main(CarpTest.java:10)
Note that as you want the method "carp" does not appear in the stacktrace. However the manipulation of stacktraces shoud only be done with greates care.
If you want to use an Exception to control the flow and what happens afterwards, a good advice it to override the fillInStackTrace() method:
public Throwable fillInStackTrace() {
return this;
}
As a result you'll have an Exception without the stacktrace and with a reduced overhead (filling in the stack trace takes time).
There is no way to removing the throwing function from the stack trace. The whole purpose of the stack trace is to log the exception path so allowing a function to opt out would defeat the purpose.
The only way you could change this is if you returned the exception instead of throwing it. But that forces you to depend on the caller to know to throw the exception.
throw die("someReason).fillInStackTrace();
Modified function
public static Exception die(String message) {
log(message);
...
return new MyException();
}
EDIT
Added the fillInStackTrace() call to ensure the stack is reset to the point of the throw.
http://java.sun.com/j2se/1.3/docs/api/java/lang/Throwable.html#Throwable()
Mmm.. you could subclass exception and override all the methods in it, and wrap the original exception. Internally, generate a new stack trace using the getStackTrace() method from the wrapped exception. I haven't looked at the source of Exception, but you may not even have to override that many methods.
Maybe you should consider approaching the problem from a different direction. Rather than modify the stack trace, why not just have your exception generator method (die in your example) return the exception rather than throw it? Then your call is throw die();.
For example:
// revised die() method:
public static MyException die(String message){
log(message);
//...
return new MyException();
}
// calling code:
throw die("a-whoopsie daisy!");
Now, granted, throw die() might seem a little un-aesthetic, so you could rename die() to newException() or something. But the requirement that the exception processing method does not show in the stack trace is met -- die() (or newException()) returns before the exception is thrown and is therefore not part of the stack to be traced.
Edit: My bad. I've spent so much time working with C# that I forgot that in Java exception stack traces are generated at instantiation, where in C#/.NET exception stack traces are generated at throw-time.
So this trick would work in C#, but not in Java.
Based on what ordnungswidrig said about setting the stack trace, and what unknown (google) said about overriding fillInStackTrace(), I've created a CarpException that does exactly what I want. Note that I found I had to strip out four stack trace frames instead of just one, as I was picking up frames from both Throwable and Exception.
public class CarpException extends Exception {
#Override
public Throwable fillInStackTrace() {
super.fillInStackTrace();
StackTraceElement[] origStackTrace = getStackTrace();
StackTraceElement[] newStackTrace = new StackTraceElement[origStackTrace.length - 4];
System.arraycopy(origStackTrace, 4, newStackTrace, 0, origStackTrace.length - 4);
setStackTrace(newStackTrace);
return this;
}
}
No can do... I tried doing something like this a while back (I was trying to capture the stack trace to log method calls before AOP existed).
The stack trace is filled in when the exception is created, and that's done natively. For the thing I was working on, I ended up reading the stack trace and looking at the second element, but that wouldn't help you here...
You might consider having your method receive a Logger as a parameter to the method. This would allow you to control the logging output based on the calling class.
I would advise against wanting your exception to exclude this part of the stack trace though. When you leave and some new person gets to maintain your code, the are not going to appreciate this non-standard error handling.
Do you throw the stack trace just to be able to analyze it? In that case you could call the getStackTrace() method on the Exception which returns a StackTraceElement[]. There you can filter the elements you don't want (f.ex. the "die" method).

Categories