Exception without stack trace in Java

JavaExceptionStack Trace

Java Problem Overview


This is probably a very naive question.

I used to believe that a Throwable in Java always contains the stack trace. Is it correct?

Now it looks like that I catch exceptions without the stack trace. Does it make sense? Is it possible to catch an exception without the stack trace?

Java Solutions


Solution 1 - Java

It's possible to catch a Throwable object in Java without a stack trace:

Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace) 

> Constructs a new throwable with the > specified detail message, cause, suppression enabled or disabled, and > writable stack trace enabled or disabled.

public Throwable fillInStackTrace()

> Fills in the execution stack trace. This method records within this > Throwable object information about the current state of the stack > frames for the current thread. > > If the stack trace of this Throwable is not writable, calling this > method has no effect.

http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html

Solution 2 - Java

For Java 6:

As Java 6 doesn't have the Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace) constructor, we can suppress the stacktrace filling using below technique (borrowed from Scala, came to know from https://stackoverflow.com/questions/299068/how-slow-are-java-exceptions)

class NoStackTraceRuntimeException extends RuntimeException {
	@Override
	public synchronized Throwable fillInStackTrace() {
		return this;
	}
}

Usage is same: throw new NoStackTraceRuntimeException (), or it's subtypes.

We can also do the same by extending Throwable:

class NoStackTraceThrowable extends Throwable {
	@Override
	public synchronized Throwable fillInStackTrace() {
		return this;
	}
}

But, a small catch is that you no longer can catch these exception using Exception as this is not subtype of Exception, instead should catch NoStackTraceThrowable or it's subtypes.

Update: For some interesting stats on performance in different usecases, check this SO question

Solution 3 - Java

For Java 7+, here is an example of an exception where the stack trace can optionally be suppressed.

public class SuppressableStacktraceException extends Exception {

    private boolean suppressStacktrace = false;

    public SuppressableStacktraceException(String message, boolean suppressStacktrace) {
	    super(message, null, suppressStacktrace, !suppressStacktrace);
	    this.suppressStacktrace = suppressStacktrace;
    }

    @Override
    public String toString() {
	    if (suppressStacktrace) {
		    return getLocalizedMessage();
	    } else {
		    return super.toString();
	    }
    }
}

This can be demonstrated with:

try {
    throw new SuppressableStacktraceException("Not suppressed", false);
} catch (SuppressableStacktraceException e) {
    e.printStackTrace();
}
try {
    throw new SuppressableStacktraceException("Suppressed", true);
} catch (SuppressableStacktraceException e) {
    e.printStackTrace();
}

This is based on the MLContextException from [Apache SystemML][1], the code of which is available on GitHub at https://github.com/apache/systemml.

[1]: http://systemml.apache.org/ "Apache SystemML"

Solution 4 - Java

The easiest way to suppress the stacktrace on any Exception is

throwable.setStackTrace(new StackTraceElement[0]);

If the exception has a cause, you may need to do the same recursively.

This also reduces the costly creation of the stack trace, as much as possible

The stacktrace for a throwable is initialized in

Throwable#fillInStackTrace()

, which is called by any constructor and thus cannot be avoided. When the stacktrace actually is used, an StackTraceElement[] is lazily constructed in

Throwable#getOurStackTrace()

which only happens, if the field Throwable.stackTrace was not already set.

Setting the stacktrace to whatever non null value, avoids the construction of the StackTraceElement[] in Throwable#getOurStackTrace() and reduces the performance penalty as much as possible.

Solution 5 - Java

As hinted at in the reply by NG., if you are seeing the stacktrace at first but then it disappears for the same exception, you are most likely seeing the effects of JVM optimization. In that case, the following questions are very similar.

https://stackoverflow.com/questions/4659151/recurring-exception-without-a-stack-trace-how-to-reset

https://stackoverflow.com/questions/2411487/nullpointerexception-in-java-with-no-stacktrace

You can turn this JVM feature off, but I would recommend keeping it enabled and working towards preventing the error in the first place, or catching it and handling it more gracefully.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichaelView Question on Stackoverflow
Solution 1 - JavaAlex WView Answer on Stackoverflow
Solution 2 - JavamanikantaView Answer on Stackoverflow
Solution 3 - JavaDeronView Answer on Stackoverflow
Solution 4 - JavaStefan Isele - prefabware.comView Answer on Stackoverflow
Solution 5 - JavarougouView Answer on Stackoverflow