Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any reason to set an exception's cause to itself?

Tags:

java

exception

I've come across some places in java libraries that I'm building against where the cause of an exception is set to the exception itself.

Is there any reason for the exception to reference itself as its cause?

EDIT

As requested, here is a concrete example:

enter image description here

like image 400
Matt Mills Avatar asked Feb 10 '12 19:02

Matt Mills


1 Answers

I have frequently seen exceptions thrown by frameworks or libraries such as Hibernate or Spring reference themselves as the cause (confusing the debugger GUI in the process).

I always wondered why they did this since it seems like such a bad idea. And today it actually caused a problem when I was trying to serialize one to JSON : bam, enless cycle.

So I investigated it a bit further :

In the source code of Throwable (all source code listed here is from JDK 1.7) we have this :

 /**
     * The throwable that caused this throwable to get thrown, or null if this
     * throwable was not caused by another throwable, or if the causative
     * throwable is unknown.  If this field is equal to this throwable itself,
     * it indicates that the cause of this throwable has not yet been
     * initialized.
     *
     * @serial
     * @since 1.4
     */
    private Throwable cause = this;

Now I specifically met the problem with an exception class that extended RuntimeException, so I went from there. One of the constructors of RuntimeException :

/** Constructs a new runtime exception with the specified detail message.
     * The cause is not initialized, and may subsequently be initialized by a
     * call to {@link #initCause}.
     *
     * @param   message   the detail message. The detail message is saved for
     *          later retrieval by the {@link #getMessage()} method.
     */
    public RuntimeException(String message) {
        super(message);
    }

Constructor of Exception called by the above:

 /**
     * Constructs a new exception with the specified detail message.  The
     * cause is not initialized, and may subsequently be initialized by
     * a call to {@link #initCause}.
     *
     * @param   message   the detail message. The detail message is saved for
     *          later retrieval by the {@link #getMessage()} method.
     */
    public Exception(String message) {
        super(message);
    }

Constructor of Throwable called by the above :

/**
     * Constructs a new throwable with the specified detail message.  The
     * cause is not initialized, and may subsequently be initialized by
     * a call to {@link #initCause}.
     *
     * <p>The {@link #fillInStackTrace()} method is called to initialize
     * the stack trace data in the newly created throwable.
     *
     * @param   message   the detail message. The detail message is saved for
     *          later retrieval by the {@link #getMessage()} method.
     */
public Throwable(String message) {
    fillInStackTrace();
    detailMessage = message;
}

fillInStackTrace is a native method and desn't seem to modify the cause field.

So as you can see, unless the initCause method is called subsequently, the cause field is never changed from the original value of this.

Conclusion : if you create a new Exception (or one of the many many subclasses that exist in the wild and don't override this behaviour) using a constructor that doesn't take a cause argument, and you don't call the initCause method, the cause of the exception will be itself !

So I guess that should make it a very common occurrence.

like image 114
Pierre Henry Avatar answered Nov 13 '22 13:11

Pierre Henry