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 | 2743 |
Number of Domain Exception Types (Thrown or Caught) | 10 |
Number of Domain Checked Exception Types | 7 |
Number of Domain Runtime Exception Types | 0 |
Number of Domain Unknown Exception Types | 3 |
nTh = Number of Throw | 522 |
nTh = Number of Throw in Catch | 53 |
Number of Catch-Rethrow (may not be correct) | 6 |
nC = Number of Catch | 617 |
nCTh = Number of Catch with Throw | 51 |
Number of Empty Catch (really Empty) | 24 |
Number of Empty Catch (with comments) | 131 |
Number of Empty Catch | 155 |
nM = Number of Methods | 13568 |
nbFunctionWithCatch = Number of Methods with Catch | 426 / 13568 |
nbFunctionWithThrow = Number of Methods with Throw | 398 / 13568 |
nbFunctionWithThrowS = Number of Methods with ThrowS | 421 / 13568 |
nbFunctionTransmitting = Number of Methods with "Throws" but NO catch, NO throw (only transmitting) | 351 / 13568 |
P1 = nCTh / nC | 8.3% (0.083) |
P2 = nMC / nM | 3.1% (0.031) |
P3 = nbFunctionWithThrow / nbFunction | 2.9% (0.029) |
P4 = nbFunctionTransmitting / nbFunction | 2.6% (0.026) |
P5 = nbThrowInCatch / nbThrow | 10.2% (0.102) |
R2 = nCatch / nThrow | 1.182 |
A1 = Number of Caught Exception Types From External Libraries | 34 |
A2 = Number of Reused Exception Types From External Libraries (thrown from application code) | 13 |
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) | BackingStoreException | 0 | 0 |
8
|
5
|
1
|
0 |
unknown | (Lib) | BundleException | 0 | 0 | 0 |
1
|
0 | 0 |
unknown | (Lib) | ClassCastException | 0 | 0 | 0 |
7
|
2
|
0 |
unknown | (Lib) | ClassNotFoundException | 0 | 0 |
2
|
10
|
0 | 0 |
unknown | (Lib) | CloneNotSupportedException | 0 | 0 | 0 |
1
|
0 | 0 |
checked | (Domain) |
CommandException
public abstract class CommandException extends Exception { /** * Generated serial version UID for this class. * * @since 3.4 */ private static final long serialVersionUID= 1776879459633730964L; private Throwable cause; /** * Creates a new instance of this class with the specified detail message. * * @param message * the detail message. */ public CommandException(String message) { super(message); } /** * Creates a new instance of this class with the specified detail message * and cause. * * @param message * the detail message. * @param cause * the cause. */ public CommandException(String message, Throwable cause) { super(message); // don't pass the cause to super, to allow compilation against JCL Foundation this.cause = cause; } /** * Returns the cause of this throwable or <code>null</code> if the * cause is nonexistent or unknown. * * @return the cause or <code>null</code> * @since 3.1 */ public Throwable getCause() { return cause; } } |
0 | 0 |
1
|
3
|
0 | 0 |
checked | (Domain) |
CommandNotMappedException
public class CommandNotMappedException extends CommandException { private static final long serialVersionUID = 1L; /** * @param message */ public CommandNotMappedException(String message) { super(message); } /** * @param message * @param cause */ public CommandNotMappedException(String message, Throwable cause) { super(message, cause); } } |
3 | 0 | 1 | 0 | 0 | 0 |
checked | (Domain) |
ContextException
public abstract class ContextException extends Exception { /** * Generated serial version UID for this class. * * @since 3.4 */ private static final long serialVersionUID= -5143404124388080211L; private Throwable cause; /** * Creates a new instance of this class with the specified detail message. * * @param message * the detail message. */ public ContextException(String message) { super(message); } /** * Creates a new instance of this class with the specified detail message * and cause. * * @param message * the detail message. * @param cause * the cause. */ public ContextException(String message, Throwable cause) { super(message); // don't pass the cause to super, to allow compilation against JCL Foundation this.cause = cause; } /** * Returns the cause of this throwable or <code>null</code> if the * cause is nonexistent or unknown. * * @return the cause or <code>null</code> * @since 3.1 */ public Throwable getCause() { return cause; } } |
0 | 0 | 0 | 0 | 0 | 0 |
unknown | (Lib) | CoreException |
14
|
2
|
66
|
85
|
6
|
0 |
unknown | (Lib) | DataFormatException | 0 | 0 |
1
|
2
|
0 | 0 |
unknown | (Lib) | DeviceResourceException | 0 | 0 | 0 |
7
|
0 | 0 |
runtime | (Lib) | Error |
12
|
10
|
0 | 0 | 0 | 0 |
checked | (Lib) | Exception | 0 | 0 |
41
|
30
|
6
|
0 |
checked | (Domain) |
ExecutionException
public final class ExecutionException extends CommandException { /** * Generated serial version UID for this class. * * @since 3.1 */ private static final long serialVersionUID = 3258130262767448120L; /** * Creates a new instance of this class with the specified detail message * and cause. * * @param message * the detail message. * @param cause * the cause. */ public ExecutionException(String message, Throwable cause) { super(message, cause); } /** * Constructs a new instance of <code>ExecutionException</code> using an * instance of the new <code>ExecutionException</code>. * * @param e * The exception from which this exception should be created; * must not be <code>null</code>. * @since 3.1 */ public ExecutionException(final org.eclipse.core.commands.ExecutionException e) { super(e.getMessage(), e); } } |
24
|
10
|
72
|
21
|
4
|
0 |
unknown | (Lib) | FileNotFoundException | 0 | 0 | 0 |
5
|
0 | 0 |
unknown | (Lib) | GeneralSecurityException | 0 | 0 | 0 |
2
|
0 | 0 |
checked | (Lib) | IOException |
1
|
1
|
13
|
62
|
2
|
0 |
unknown | (Lib) | IllegalAccessException | 0 | 0 |
3
|
16
|
1
|
1 |
runtime | (Lib) | IllegalArgumentException |
150
|
0 |
3
|
16
|
1
|
0 |
runtime | (Lib) | IllegalStateException |
18
|
0 |
14
|
6
|
0 | 0 |
unknown | (Lib) | InstantiationException | 0 | 0 | 0 |
1
|
0 | 0 |
unknown | (Lib) | InterruptedException |
2
|
0 |
14
|
17
|
0 | 0 |
unknown | (Lib) | InvalidRegistryObjectException | 0 | 0 | 0 |
2
|
0 | 0 |
unknown | (Lib) | InvalidSyntaxException | 0 | 0 | 0 |
1
|
0 | 0 |
unknown | (Lib) | InvocationTargetException |
1
|
1
|
16
|
23
|
5
|
1 |
unknown | (Lib) | LinkageError | 0 | 0 | 0 |
1
|
0 | 0 |
unknown | (Lib) | MalformedURLException | 0 | 0 |
1
|
5
|
0 | 0 |
unknown | (Lib) | MissingResourceException | 0 | 0 | 0 |
2
|
0 | 0 |
unknown | (Domain) |
MultiPartInitException
public class MultiPartInitException extends WorkbenchException { private IWorkbenchPartReference[] references; private PartInitException[] exceptions; /** * Creates a new exception object. Note that as of 3.5, this constructor * expects exactly one exception object in the given array, with all other * array positions being <code>null</code>. The restriction may be lifted in * the future, and clients of this class must not make this assumption. * * @param references * @param exceptions */ public MultiPartInitException(IWorkbenchPartReference[] references, PartInitException[] exceptions) { super(exceptions[findSingleException(exceptions)].getStatus()); this.references = references; this.exceptions = exceptions; } /** * Returns an array of part references, containing references of parts that * were intialized correctly. Any number of elements of the returned array * may have a <code>null</code> value. * * @return the part reference array */ public IWorkbenchPartReference[] getReferences() { return references; } /** * Returns an array of exceptions, corresponding to parts that could not be * intialized correctly. At least one element of the returned array will * have a non-<code>null</code> value. * * @return the exception array */ public PartInitException[] getExceptions() { return exceptions; } private static int findSingleException(PartInitException[] exceptions) { int index = -1; for (int i = 0; i < exceptions.length; i++) { if (exceptions[i] != null) { if (index == -1) { index = i; } else throw new IllegalArgumentException(); } } if (index == -1) { throw new IllegalArgumentException(); } return index; } private static final long serialVersionUID = -9138185942975165490L; } |
1
|
0 |
1
|
0 | 0 | 0 |
unknown | (Lib) | NoClassDefFoundError | 0 | 0 | 0 |
1
|
0 | 0 |
unknown | (Lib) | NoSuchMethodException | 0 | 0 |
3
|
18
|
3
|
3 |
checked | (Domain) |
NotDefinedException
public final class NotDefinedException extends CommandException { /** * Generated serial version UID for this class. * * @since 3.1 */ private static final long serialVersionUID = 3257572788998124596L; /** * Creates a new instance of this class with the specified detail message. * * @param s * the detail message. */ public NotDefinedException(String s) { super(s); } /** * Constructs a legacy <code>NotDefinedException</code> based on the new * <code>NotDefinedException</code>. * * @param e * The exception from which this exception should be created; * must not be <code>null</code>. * @since 3.1 */ public NotDefinedException( final org.eclipse.core.commands.common.NotDefinedException e) { super(e.getMessage(), e); } }public final class NotDefinedException extends ContextException { /** * Generated serial version UID for this class. * * @since 3.1 */ private static final long serialVersionUID = 3833750983926167092L; /** * Creates a new instance of this class with the specified detail message. * * @param message * the detail message. */ public NotDefinedException(String message) { super(message); } /** * Constructs a new instance of <code>NotDefinedException</code>. * * @param e * The exception being thrown; must not be <code>null</code>. * @since 3.1 */ public NotDefinedException( org.eclipse.core.commands.common.NotDefinedException e) { super(e.getMessage(), e); } }public final class NotDefinedException extends Exception { /** * Generated serial version UID for this class. * @since 3.1 */ private static final long serialVersionUID = 4050201929596811061L; /** * Creates a new instance of this class with no specified detail message. */ public NotDefinedException() { //no-op } /** * Creates a new instance of this class with the specified detail message. * * @param s * the detail message. */ public NotDefinedException(String s) { super(s); } } |
16
|
8
|
29
|
95
|
12
|
4 |
unknown | (Lib) | NotEnabledException | 0 | 0 |
6
|
13
|
0 | 0 |
checked | (Domain) |
NotHandledException
public final class NotHandledException extends CommandException { /** * Generated serial version UID for this class. * * @since 3.1 */ private static final long serialVersionUID = 3256446914827726904L; /** * Creates a new instance of this class with the specified detail message. * * @param s * the detail message. */ public NotHandledException(String s) { super(s); } /** * Constructs a legacy <code>NotHandledException</code> based on the new * <code>NotHandledException</code> * * @param e * The exception from which this exception should be created; * must not be <code>null</code>. * @since 3.1 */ public NotHandledException(final org.eclipse.core.commands.NotHandledException e) { super(e.getMessage(), e); } } |
1
|
1
|
7
|
15
|
1
|
0 |
runtime | (Lib) | NullPointerException |
165
|
0 | 0 | 0 | 0 | 0 |
unknown | (Lib) | NumberFormatException | 0 | 0 |
1
|
22
|
0 | 0 |
unknown | (Lib) | OperationCanceledException | 0 | 0 | 0 |
6
|
0 | 0 |
unknown | (Lib) | ParameterValueConversionException |
2
|
2
|
3
|
0 | 0 | 0 |
unknown | (Lib) | ParameterValuesException |
2
|
2
|
1
|
0 | 0 | 0 |
checked | (Domain) |
ParseException
public final class ParseException extends Exception { /** * Generated serial version UID for this class. * @since 3.1 */ private static final long serialVersionUID = 3257009864814376241L; /** * Constructs a <code>ParseException</code> with the specified detail * message. * * @param s * the detail message. */ public ParseException(final String s) { super(s); } } |
4
|
2
|
4
|
9
|
0 | 0 |
unknown | (Lib) | ParserConfigurationException | 0 | 0 | 0 |
2
|
1
|
1 |
unknown | (Domain) |
PartInitException
public class PartInitException extends WorkbenchException { /** * Generated serial version UID for this class. * @since 3.1 */ private static final long serialVersionUID = 3257284721296684850L; /** * Creates a new exception with the given message. * * @param message the message */ public PartInitException(String message) { super(message); } /** * Creates a new exception with the given message. * * @param message the message * @param nestedException a exception to be wrapped by this PartInitException */ public PartInitException(String message, Throwable nestedException) { super(message, nestedException); } /** * Creates a new exception with the given status object. The message * of the given status is used as the exception message. * * @param status the status object to be associated with this exception */ public PartInitException(IStatus status) { super(status); } } |
29
|
5
|
50
|
40
|
2
|
0 |
runtime | (Lib) | RuntimeException |
3
|
0 |
1
|
14
|
0
|
0 |
unknown | (Lib) | SAXException | 0 | 0 |
3
|
1
|
0 | 0 |
unknown | (Lib) | SWTError |
1
|
0 | 0 | 0 | 0 | 0 |
unknown | (Lib) | SWTException | 0 | 0 | 0 |
2
|
0 | 0 |
unknown | (Lib) | SecurityException | 0 | 0 | 0 |
4
|
1
|
0 |
checked | (Lib) | Throwable | 0 | 0 |
46
|
16
|
4
|
0 |
runtime | (Lib) | UnsupportedOperationException |
13
|
0 |
1
|
0 | 0 | 0 |
unknown | (Domain) |
WorkbenchException
public class WorkbenchException extends CoreException { /** * Generated serial version UID for this class. * @since 3.1 */ private static final long serialVersionUID = 3258125864872129078L; /** * Creates a new exception with the given message. * * @param message the message */ public WorkbenchException(String message) { this(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, message, null)); } /** * Creates a new exception with the given message. * * @param message the message * @param nestedException an exception to be wrapped by this WorkbenchException */ public WorkbenchException(String message, Throwable nestedException) { this(new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, 0, message, nestedException)); } /** * Creates a new exception with the given status object. The message * of the given status is used as the exception message. * * @param status the status object to be associated with this exception */ public WorkbenchException(IStatus status) { super(status); } } |
20
|
1
|
37
|
28
|
1
|
0 |
nF = Number of Finally | 126 |
nF = Number of Try-Finally (without catch) | 97 |
Number of Methods with Finally (nMF) | 118 / 13568 (0.9%) |
Number of Finally with a Continue | 0 |
Number of Finally with a Return | 4 |
Number of Finally with a Throw | 0 |
Number of Finally with a Break | 0 |
Number of different exception types thrown | 21 |
Number of Domain exception types thrown | 8 |
Number of different exception types caught | 41 |
Number of Domain exception types caught | 7 |
Number of exception declarations in signatures | 549 |
Number of different exceptions types declared in method signatures | 32 |
Number of library exceptions types declared in method signatures | 23 |
Number of Domain exceptions types declared in method signatures | 9 |
Number of Catch with a continue | 3 |
Number of Catch with a return | 106 |
Number of Catch with a Break | 1 |
nbIf = Number of If | 12660 |
nbFor = Number of For | 1724 |
Number of Method with an if | 5803 / 13568 |
Number of Methods with a for | 1426 / 13568 |
Number of Method starting with a try | 83 / 13568 (0.6%) |
Number of Expressions | 125114 |
Number of Expressions in try | 6776 (5.4%) |