The goal of an Exception Fact Sheet is to reveal the design of exception handling in an application.
--Maxence, Martin
For feedback, please contact Martin
| Number of Classes | 261 |
| Number of Domain Exception Types (Thrown or Caught) | 21 |
| Number of Domain Checked Exception Types | 2 |
| Number of Domain Runtime Exception Types | 19 |
| Number of Domain Unknown Exception Types | 0 |
| nTh = Number of Throw | 468 |
| nTh = Number of Throw in Catch | 54 |
| Number of Catch-Rethrow (may not be correct) | 1 |
| nC = Number of Catch | 107 |
| nCTh = Number of Catch with Throw | 51 |
| Number of Empty Catch (really Empty) | 17 |
| Number of Empty Catch (with comments) | 3 |
| Number of Empty Catch | 20 |
| nM = Number of Methods | 2581 |
| nbFunctionWithCatch = Number of Methods with Catch | 89 / 2581 |
| nbFunctionWithThrow = Number of Methods with Throw | 368 / 2581 |
| nbFunctionWithThrowS = Number of Methods with ThrowS | 117 / 2581 |
| nbFunctionTransmitting = Number of Methods with "Throws" but NO catch, NO throw (only transmitting) | 91 / 2581 |
| P1 = nCTh / nC | 47.7% (0.477) |
| P2 = nMC / nM | 3.4% (0.034) |
| P3 = nbFunctionWithThrow / nbFunction | 14.3% (0.143) |
| P4 = nbFunctionTransmitting / nbFunction | 3.5% (0.035) |
| P5 = nbThrowInCatch / nbThrow | 11.5% (0.115) |
| R2 = nCatch / nThrow | 0.229 |
| A1 = Number of Caught Exception Types From External Libraries | 23 |
| A2 = Number of Reused Exception Types From External Libraries (thrown from application code) | 16 |
W1 is a rough estimation of the richness of the exception model. It does not take into account the inheritance relationships between domain exceptions.
Proportion P1 measures the overall exception flow. According to our experience, it varies from 5% to 70%. Early-catch design generally yields a low P1, libraries that must warn clients about errors (e.g. databases) generally have a high P1.
Proportion P2 measures the dispersion of catch blocks in the application. According to our experience, it varies from 2% to 15%. A small P2 indicates a rather centralized management of errors.
R1 shows how many exceptions types from libraries (incl. JDK) are thrown from application code. For instance, IllegalArgumentException comes from the JDK but is used in many applications.
A1 measures the awareness of the application to library exceptions. A high value of A1 means either that the application is polluted with checked exceptions or that it is able to apply specific recovery depending on the library exception.
Each exception that is used at least once in the project is a dot. A orange dot represents a domain exception that is defined in the application. A blue dot exception is defined in the JDK or in a library. The x-axis represents the number of times an exception is caught, the y-axis the number of times an exception is thrown.
A (Domain) exception is defined in the application. A (Lib) exception is defined in the JDK or in a library. An exception can be thrown, thrown from within a catch, or declared in the signature of a method (usually for checked exceptions). Hovering over a number triggers showing code snippets from the application code.
A (Domain) exception is defined in the application. A (Lib) exception is defined in the JDK or in a library. An exception can be caught, and it happens that the catch block contains a throw (e.g. for wrapping a low-level exception). Hovering over a number triggers showing code snippets from the application code.
There is a common practice of throwing exceptions from within a catch block (e.g. for wrapping a low-level exception). The following table summarizes the usage of this practice in the application. The last column gives the number of times it happens for a pair of exceptions. The graph below the table graphically renders the same information. For a given node, its color represents its origin (blue means library exception, orange means domain exception); the left-most number is the number of times it is thrown, the right-most is the number of times it is caught.
Not all exceptions are thrown AND caught in the same project. The following table gives the exceptions types with respect to this. The lower left hand side sell lists all exceptions thrown but not caught (prevalent for libraries), the upper right-hand side lists all exceptions caught but not thrown (usually coming from external dependencies).
| Thrown | Not Thrown | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Caught |
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Not caught |
|
The following shows the methods that are called inside catch blocks (first column) and finally blocks (second column). For each method, we give the number of times it is called in a catch block (second sub-column), and the total number of calls (third sub-column). If the method name is red, it means that it is only called from catch/finally blocks. Hovering over a number triggers showing code snippets from the application code.
| Catch | Finally | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
This table concatenates the results of the previous tables.
| Checked/Runtime | Type | Exception | Thrown | Thrown from Catch | Declared | Caught directly | Caught with Thrown |
Caught with Thrown Runtime |
|---|---|---|---|---|---|---|---|---|
| unknown | (Lib) | . | 0 | 0 | 0 | 0 | 0 | 0 |
| unknown | (Lib) | ArrayIndexOutOfBoundsException |
13
|
0 | 0 | 0 | 0 | 0 |
| unknown | (Lib) | ArrayStoreException | 0 | 0 | 0 |
4
|
4
|
0 |
| unknown | (Lib) | AssertionError |
3
|
3
|
0 | 0 | 0 | 0 |
| unknown | (Lib) | ClassCastException |
15
|
4
|
0 |
4
|
0 | 0 |
| unknown | (Lib) | ClassNotFoundException | 0 | 0 |
26
|
7
|
1
|
0 |
| unknown | (Lib) | CloneNotSupportedException | 0 | 0 |
1
|
18
|
16
|
0 |
| runtime | (Domain) |
ConcurrentModificationException
public class ConcurrentModificationException extends RuntimeException {
/**
* Constructs a ConcurrentModificationException with no
* detail message.
*/
public ConcurrentModificationException() {
}
/**
* Constructs a <tt>ConcurrentModificationException</tt> with the
* specified detail message.
*
* @param message the detail message pertaining to this exception.
*/
public ConcurrentModificationException(String message) {
super(message);
}
}
|
31
|
3
|
0 | 0 | 0 | 0 |
| runtime | (Domain) |
DuplicateFormatFlagsException
public class DuplicateFormatFlagsException extends IllegalFormatException {
private static final long serialVersionUID = 18890531L;
private String flags;
/**
* Constructs an instance of this class with the specified flags.
*
* @param f
* The set of format flags which contain a duplicate flag.
*/
public DuplicateFormatFlagsException(String f) {
if (f == null)
throw new NullPointerException();
this.flags = f;
}
/**
* Returns the set of flags which contains a duplicate flag.
*
* @return The flags
*/
public String getFlags() {
return flags;
}
public String getMessage() {
return String.format("Flags = '%s'", flags);
}
}
|
1
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Domain) |
EmptyStackException
public
class EmptyStackException extends RuntimeException {
/**
* Constructs a new <code>EmptyStackException</code> with <tt>null</tt>
* as its error message string.
*/
public EmptyStackException() {
}
}
|
1
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Lib) | Error |
3
|
2
|
0 | 0 | 0 | 0 |
| checked | (Lib) | Exception | 0 | 0 |
1
|
6
|
1
|
1 |
| runtime | (Domain) |
FormatFlagsConversionMismatchException
public class FormatFlagsConversionMismatchException
extends IllegalFormatException
{
private static final long serialVersionUID = 19120414L;
private String f;
private char c;
/**
* Constructs an instance of this class with the specified flag
* and conversion.
*
* @param f
* The flag
*
* @param c
* The conversion
*/
public FormatFlagsConversionMismatchException(String f, char c) {
if (f == null)
throw new NullPointerException();
this.f = f;
this.c = c;
}
/**
* Returns the incompatible flag.
*
* @return The flag
*/
public String getFlags() {
return f;
}
/**
* Returns the incompatible conversion.
*
* @return The conversion
*/
public char getConversion() {
return c;
}
public String getMessage() {
return "Conversion = " + c + ", Flags = " + f;
}
}
|
1
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Domain) |
FormatterClosedException
public class FormatterClosedException extends IllegalStateException {
private static final long serialVersionUID = 18111216L;
/**
* Constructs an instance of this class.
*/
public FormatterClosedException() { }
}
|
1
|
0 | 0 | 0 | 0 | 0 |
| checked | (Lib) | IOException | 0 | 0 |
89
|
13
|
0 | 0 |
| unknown | (Lib) | IllegalAccessException | 0 | 0 |
1
|
1
|
1
|
0 |
| runtime | (Lib) | IllegalArgumentException |
97
|
0 | 0 |
1
|
0 | 0 |
| runtime | (Domain) |
IllegalFormatCodePointException
public class IllegalFormatCodePointException extends IllegalFormatException {
private static final long serialVersionUID = 19080630L;
private int c;
/**
* Constructs an instance of this class with the specified illegal code
* point as defined by {@link Character#isValidCodePoint}.
*
* @param c
* The illegal Unicode code point
*/
public IllegalFormatCodePointException(int c) {
this.c = c;
}
/**
* Returns the illegal code point as defined by {@link
* Character#isValidCodePoint}.
*
* @return The illegal Unicode code point
*/
public int getCodePoint() {
return c;
}
public String getMessage() {
return String.format("Code point = %#x", c);
}
}
|
3
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Domain) |
IllegalFormatConversionException
public class IllegalFormatConversionException extends IllegalFormatException {
private static final long serialVersionUID = 17000126L;
private char c;
private Class arg;
/**
* Constructs an instance of this class with the mismatched conversion and
* the corresponding argument class.
*
* @param c
* Inapplicable conversion
*
* @param arg
* Class of the mismatched argument
*/
public IllegalFormatConversionException(char c, Class<?> arg) {
if (arg == null)
throw new NullPointerException();
this.c = c;
this.arg = arg;
}
/**
* Returns the inapplicable conversion.
*
* @return The inapplicable conversion
*/
public char getConversion() {
return c;
}
/**
* Returns the class of the mismatched argument.
*
* @return The class of the mismatched argument
*/
public Class<?> getArgumentClass() {
return arg;
}
// javadoc inherited from Throwable.java
public String getMessage() {
return String.format("%c != %s", c, arg.getName());
}
}
|
1
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Domain) |
IllegalFormatException
public class IllegalFormatException extends IllegalArgumentException {
private static final long serialVersionUID = 18830826L;
// package-private to prevent explicit instantiation
IllegalFormatException() { }
}
|
0 | 0 | 0 | 0 | 0 | 0 |
| runtime | (Domain) |
IllegalFormatFlagsException
public class IllegalFormatFlagsException extends IllegalFormatException {
private static final long serialVersionUID = 790824L;
private String flags;
/**
* Constructs an instance of this class with the specified flags.
*
* @param f
* The set of format flags which contain an illegal combination
*/
public IllegalFormatFlagsException(String f) {
if (f == null)
throw new NullPointerException();
this.flags = f;
}
/**
* Returns the set of flags which contains an illegal combination.
*
* @return The flags
*/
public String getFlags() {
return flags;
}
public String getMessage() {
return "Flags = '" + flags + "'";
}
}
|
3
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Domain) |
IllegalFormatPrecisionException
public class IllegalFormatPrecisionException extends IllegalFormatException {
private static final long serialVersionUID = 18711008L;
private int p;
/**
* Constructs an instance of this class with the specified precision.
*
* @param p
* The precision
*/
public IllegalFormatPrecisionException(int p) {
this.p = p;
}
/**
* Returns the precision
*
* @return The precision
*/
public int getPrecision() {
return p;
}
public String getMessage() {
return Integer.toString(p);
}
}
|
6
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Domain) |
IllegalFormatWidthException
public class IllegalFormatWidthException extends IllegalFormatException {
private static final long serialVersionUID = 16660902L;
private int w;
/**
* Constructs an instance of this class with the specified width.
*
* @param w
* The width
*/
public IllegalFormatWidthException(int w) {
this.w = w;
}
/**
* Returns the width
*
* @return The width
*/
public int getWidth() {
return w;
}
public String getMessage() {
return Integer.toString(w);
}
}
|
3
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Lib) | IllegalStateException |
31
|
1
|
0 | 0 | 0 | 0 |
| unknown | (Lib) | IndexOutOfBoundsException |
34
|
5
|
0 |
5
|
5
|
5 |
| runtime | (Domain) |
InputMismatchException
public
class InputMismatchException extends NoSuchElementException {
/**
* Constructs an <code>InputMismatchException</code> with <tt>null</tt>
* as its error message string.
*/
public InputMismatchException() {
super();
}
/**
* Constructs an <code>InputMismatchException</code>, saving a reference
* to the error message string <tt>s</tt> for later retrieval by the
* <tt>getMessage</tt> method.
*
* @param s the detail message.
*/
public InputMismatchException(String s) {
super(s);
}
}
|
9
|
8
|
0 | 0 | 0 | 0 |
| unknown | (Lib) | InternalError |
24
|
17
|
0 | 0 | 0 | 0 |
| unknown | (Lib) | InterruptedException | 0 | 0 | 0 |
1
|
0 | 0 |
| checked | (Domain) |
InvalidPropertiesFormatException
public class InvalidPropertiesFormatException extends IOException {
/**
* Constructs an InvalidPropertiesFormatException with the specified
* cause.
*
* @param cause the cause (which is saved for later retrieval by the
* {@link Throwable#getCause()} method).
*/
public InvalidPropertiesFormatException(Throwable cause) {
super(cause==null ? null : cause.toString());
this.initCause(cause);
}
/**
* Constructs an InvalidPropertiesFormatException with the specified
* detail message.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link Throwable#getMessage()} method.
*/
public InvalidPropertiesFormatException(String message) {
super(message);
}
/**
* Throws NotSerializableException, since InvalidPropertiesFormatException
* objects are not intended to be serializable.
*/
private void writeObject(java.io.ObjectOutputStream out)
throws NotSerializableException
{
throw new NotSerializableException("Not serializable.");
}
/**
* Throws NotSerializableException, since InvalidPropertiesFormatException
* objects are not intended to be serializable.
*/
private void readObject(java.io.ObjectInputStream in)
throws NotSerializableException
{
throw new NotSerializableException("Not serializable.");
}
}
|
2
|
1
|
2
|
0 | 0 | 0 |
| unknown | (Lib) | LinkageError | 0 | 0 | 0 |
1
|
0 | 0 |
| runtime | (Domain) |
MissingFormatArgumentException
public class MissingFormatArgumentException extends IllegalFormatException {
private static final long serialVersionUID = 19190115L;
private String s;
/**
* Constructs an instance of this class with the unmatched format
* specifier.
*
* @param s
* Format specifier which does not have a corresponding argument
*/
public MissingFormatArgumentException(String s) {
if (s == null)
throw new NullPointerException();
this.s = s;
}
/**
* Returns the unmatched format specifier.
*
* @return The unmatched format specifier
*/
public String getFormatSpecifier() {
return s;
}
public String getMessage() {
return "Format specifier '" + s + "'";
}
}
|
3
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Domain) |
MissingFormatWidthException
public class MissingFormatWidthException extends IllegalFormatException {
private static final long serialVersionUID = 15560123L;
private String s;
/**
* Constructs an instance of this class with the specified format
* specifier.
*
* @param s
* The format specifier which does not have a width
*/
public MissingFormatWidthException(String s) {
if (s == null)
throw new NullPointerException();
this.s = s;
}
/**
* Returns the format specifier which does not have a width.
*
* @return The format specifier which does not have a width
*/
public String getFormatSpecifier() {
return s;
}
public String getMessage() {
return s;
}
}
|
5
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Domain) |
MissingResourceException
public
class MissingResourceException extends RuntimeException {
/**
* Constructs a MissingResourceException with the specified information.
* A detail message is a String that describes this particular exception.
* @param s the detail message
* @param className the name of the resource class
* @param key the key for the missing resource.
*/
public MissingResourceException(String s, String className, String key) {
super(s);
this.className = className;
this.key = key;
}
/**
* Constructs a <code>MissingResourceException</code> with
* <code>message</code>, <code>className</code>, <code>key</code>,
* and <code>cause</code>. This constructor is package private for
* use by <code>ResourceBundle.getBundle</code>.
*
* @param message
* the detail message
* @param className
* the name of the resource class
* @param key
* the key for the missing resource.
* @param cause
* the cause (which is saved for later retrieval by the
* {@link Throwable.getCause()} method). (A null value is
* permitted, and indicates that the cause is nonexistent
* or unknown.)
*/
MissingResourceException(String message, String className, String key, Throwable cause) {
super(message, cause);
this.className = className;
this.key = key;
}
/**
* Gets parameter passed by constructor.
*
* @return the name of the resource class
*/
public String getClassName() {
return className;
}
/**
* Gets parameter passed by constructor.
*
* @return the key for the missing resource
*/
public String getKey() {
return key;
}
//============ privates ============
// serialization compatibility with JDK1.1
private static final long serialVersionUID = -4876345176062000401L;
/**
* The class name of the resource bundle requested by the user.
* @serial
*/
private String className;
/**
* The name of the specific resource requested by the user.
* @serial
*/
private String key;
}
|
4
|
0 |
2
|
3
|
0 | 0 |
| unknown | (Lib) | NegativeArraySizeException | 1 | 0 | 0 | 0 | 0 | 0 |
| unknown | (Lib) | NoSuchAlgorithmException | 0 | 0 | 0 |
1
|
1
|
0 |
| runtime | (Domain) |
NoSuchElementException
public
class NoSuchElementException extends RuntimeException {
/**
* Constructs a <code>NoSuchElementException</code> with <tt>null</tt>
* as its error message string.
*/
public NoSuchElementException() {
super();
}
/**
* Constructs a <code>NoSuchElementException</code>, saving a reference
* to the error message string <tt>s</tt> for later retrieval by the
* <tt>getMessage</tt> method.
*
* @param s the detail message.
*/
public NoSuchElementException(String s) {
super(s);
}
}
|
46
|
2
|
0 |
6
|
6
|
1 |
| unknown | (Lib) | NoSuchFieldException | 0 | 0 | 0 |
1
|
1
|
0 |
| unknown | (Lib) | NotSerializableException |
2
|
0 |
2
|
0 | 0 | 0 |
| runtime | (Lib) | NullPointerException |
62
|
0 | 0 |
6
|
1
|
0 |
| unknown | (Lib) | NumberFormatException | 0 | 0 | 0 |
19
|
8
|
8 |
| unknown | (Lib) | OutOfMemoryError |
2
|
0 | 0 | 0 | 0 | 0 |
| unknown | (Lib) | ParserConfigurationException | 0 | 0 | 0 |
2
|
1
|
1 |
| unknown | (Lib) | PrivilegedActionException | 0 | 0 | 0 |
2
|
5
|
1 |
| runtime | (Lib) | RuntimeException |
1
|
1
|
0 | 0 | 0 | 0 |
| unknown | (Lib) | SAXException |
1
|
0 |
5
|
1
|
1
|
0 |
| unknown | (Lib) | SecurityException |
1
|
0 | 0 |
1
|
0 | 0 |
| runtime | (Domain) |
ServiceConfigurationError
public class ServiceConfigurationError
extends Error
{
private static final long serialVersionUID = 74132770414881L;
/**
* Constructs a new instance with the specified message.
*
* @param msg The message, or <tt>null</tt> if there is no message
*
*/
public ServiceConfigurationError(String msg) {
super(msg);
}
/**
* Constructs a new instance with the specified message and cause.
*
* @param msg The message, or <tt>null</tt> if there is no message
*
* @param cause The cause, or <tt>null</tt> if the cause is nonexistent
* or unknown
*/
public ServiceConfigurationError(String msg, Throwable cause) {
super(msg, cause);
}
}
|
2
|
0 |
5
|
0 | 0 | 0 |
| checked | (Lib) | Throwable | 0 | 0 |
1
|
1
|
0 | 0 |
| checked | (Domain) |
TooManyListenersException
public class TooManyListenersException extends Exception {
/**
* Constructs a TooManyListenersException with no detail message.
* A detail message is a String that describes this particular exception.
*/
public TooManyListenersException() {
super();
}
/**
* Constructs a TooManyListenersException with the specified detail message.
* A detail message is a String that describes this particular exception.
* @param s the detail message
*/
public TooManyListenersException(String s) {
super(s);
}
}
|
0 | 0 | 0 | 0 | 0 | 0 |
| unknown | (Lib) | TransformerConfigurationException | 0 | 0 | 0 |
1
|
0 | 0 |
| unknown | (Lib) | TransformerException | 0 | 0 | 0 |
1
|
1
|
0 |
| runtime | (Domain) |
UnknownFormatConversionException
public class UnknownFormatConversionException extends IllegalFormatException {
private static final long serialVersionUID = 19060418L;
private String s;
/**
* Constructs an instance of this class with the unknown conversion.
*
* @param s
* Unknown conversion
*/
public UnknownFormatConversionException(String s) {
if (s == null)
throw new NullPointerException();
this.s = s;
}
/**
* Returns the unknown conversion.
*
* @return The unknown conversion.
*/
public String getConversion() {
return s;
}
// javadoc inherited from Throwable.java
public String getMessage() {
return String.format("Conversion = '%s'", s);
}
}
|
4
|
0 | 0 | 0 | 0 | 0 |
| runtime | (Domain) |
UnknownFormatFlagsException
public class UnknownFormatFlagsException extends IllegalFormatException {
private static final long serialVersionUID = 19370506L;
private String flags;
/**
* Constructs an instance of this class with the specified flags.
*
* @param f
* The set of format flags which contain an unknown flag
*/
public UnknownFormatFlagsException(String f) {
if (f == null)
throw new NullPointerException();
this.flags = f;
}
/**
* Returns the set of flags which contains an unknown flag.
*
* @return The flags
*/
public String getFlags() {
return flags;
}
// javadoc inherited from Throwable.java
public String getMessage() {
return "Flags = " + flags;
}
}
|
1
|
0 | 0 | 0 | 0 | 0 |
| unknown | (Lib) | UnsupportedEncodingException | 0 | 0 | 6 |
1
|
1
|
0 |
| runtime | (Lib) | UnsupportedOperationException |
37
|
0 | 0 | 0 | 0 | 0 |
| nF = Number of Finally | 5 |
| nF = Number of Try-Finally (without catch) | 3 |
| Number of Methods with Finally (nMF) | 6 / 2581 (0.2%) |
| Number of Finally with a Continue | 0 |
| Number of Finally with a Return | 0 |
| Number of Finally with a Throw | 0 |
| Number of Finally with a Break | 0 |
| Number of different exception types thrown | 35 |
| Number of Domain exception types thrown | 19 |
| Number of different exception types caught | 25 |
| Number of Domain exception types caught | 2 |
| Number of exception declarations in signatures | 153 |
| Number of different exceptions types declared in method signatures | 16 |
| Number of library exceptions types declared in method signatures | 13 |
| Number of Domain exceptions types declared in method signatures | 3 |
| Number of Catch with a continue | 0 |
| Number of Catch with a return | 7 |
| Number of Catch with a Break | 0 |
| nbIf = Number of If | 2364 |
| nbFor = Number of For | 337 |
| Number of Method with an if | 914 / 2581 |
| Number of Methods with a for | 272 / 2581 |
| Number of Method starting with a try | 20 / 2581 (0.8%) |
| Number of Expressions | 23077 |
| Number of Expressions in try | 770 (3.3%) |