Exception without stack trace in Java

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?


Solution 1:

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:

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 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:

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, the code of which is available on GitHub at https://github.com/apache/systemml.