Exception/Error | Typical circumstances when thrown | Example |
NullPointerException |
Attempt to access a field or method on a null reference. |
Object o = null;
o.toString();
|
Attempt to unbox a null Integer, Boolean etc |
Boolean b = null;
if (b) {
...
}
Integer i = null;
if (i == 3) {
...
}
|
Attempt to synhcronize on a null reference |
Object obj = null;
synchronized (obj) {
...
}
|
StackOverflowError |
A chain of too many methods or constructors calling into one another: usually caused by a method or constructor that
recursively calls itself without returning. This eventually causes the special area of memory known as the stack
to run out. Occasionally, a correctly functioning program that performs deep levels of
recursion may still get this error, in which case it may be solved by increasing the thread's stack size.
You can do this application-wide by setting the -Xss... JVM parameter, e.g. -Xss32m.
|
private void badMethod() {
badMethod();
} |
ArithmeticException |
Thrown by an arithmetic operation that is not permitted, generally an integer division by zero. (Note that floating point
divisions by zero are allowed, since a float or double can represent infinity. If you are not
careful, this can mean that bugs where you accidentally divide by zero are hard to track down...!)
|
int seconds = 0;
int rate = items / seconds;
|
OutOfMemoryError |
Thrown when the JVM cannot allocate memory for a given object. In principle, this means that there is not a
big enough area of heap space available, even after garbage collection and defragmentation (i.e. removing
objects no longer rerferenced and earranging objects in memory to make a large enough space available).
It could also
mean that a memory allocation request is simply invalid in principle (a request to create an array that is bigger than the JVM
knows it can create). The getMessage() on the OutOfMemoryError itself will sometimes provide
a more detailed reason such as Requested array size exceeds VM limit.
In practice, the situation can be complex in the case of a resource-intensive multithreaded application
running on a modern server-class JVM. For example, it is possible to get an OutOfMemoryError when theoretically,
space could have been made available, but the garbage collector is starved of CPU time to free up the memory.
Whether or not it is safe and possible to catch an OutOfMemoryError therefore depends very much on the
situation: the failure to allocate memory for one specific object by one thread could actually be caused by a memory leak
in an unrelated thread, or by the GC being starved of resources. Whether or not your application is left in a safe state when
this occurs may be somewhat unpredictable.
On the other hand, an OutOfMemoryError from a simple array allocation can generally be caught safely.
|
iint[] x = new int[1_000_000_000];
byte[] x = new byte[Integer.MAX_VALUE];
|
InterruptedException |
Usually, an InterruptedException is thrown when interrupt() is called on the thread in question,
and it is currently in a blocking call such as Object.wait() or Thread.sleep(). Under extremely rare circumstances,
the reason for the interruption could be from the OS itself. If you get an InterruptedException and you haven't
specifically called interrupt() on the thread being interrupted, then bear in mind that other APIs
may internally interrupt the threads they manage. If you are using the Executor framework, for example, note that
calling cancel() on a scheduled task can optionally interrupt the task with a thread interrupt.
|
See e.g. Future.cancel() |
ExceptionInInitializerError |
Occurs if you have a static field or static block in your class which itself throws an exception,
preventing your class from being initialised. In the example here, attempting to initialise the static field
throws a PatternSyntaxException because the regular expression is malformed. This in turn means the class cannot
be initialised, and so the first time it needs to be loaded, an ExceptionInInitializerError will be thrown.
|
lass MyClass {
// Erroneous regex: will cause class initialisation to fail
private static Pattern PATT = Pattern.compile("(");
}
new MyClass(); | |
NoClassDefFoundError |
In principle, this error is thrown if the JVM cannot find a class that it needs to load "in the normal course of execution",
for example, because your code is attempting to create an object of the relevant class or is calling a static method on it,
or refers to it in an instanceof etc.
This is different to a ClassNotFoundException, which occurs when you deliberately try to load a class by
calling Class.forName(...).
In practice, the JVM may also throw a NoClassDefFoundError to indicate that the class was previously found successfully,
but that an error occurred when attempting to initialise it the first time. On that initial load,
an ExceptionInInitializerError would have been thrown. But from then on, the JVM will not
attempt to re-initialise it, and will instead throw a NoClassDefFoundError with the message Could not initialize class.
|
class MyClass {
// Erroneous regex: will cause class initialisation to fail
private static Pattern PATT = Pattern.compile("(");
}
// Class loaded but not initialised
try {
new MyClass();
} catch (Throwable t) {}
// Throws a NoClassDefFoundError
new MyClass(); |
IllegalMonitorStateException |
Caused when you attempt to call wait() on an object but you have not synchronized on that object. A call to
wait() should be in a block of code that synchronizes on the object in question. (The synchronization lock will be temporarily
released during the actual wait then re-acquired by the time the wait() call returns.)
|
|
AbstractMethodError |
This error means that your code has attempted to call an abstract method, in other words a method of an abstract
class or interface that the subclass should define but does not. If you get an AbstractMethodError, the likely reason is
that some of your code was compiled against one version of a class or jar and then running against a different version:
at compile time, the method definition was present, but at runtime, it is absent (or its signature no longer matches).
Subtly, this could include the case where conflicting definitions of a class are present in different jars pathed into
your classpaths, with one version being picked up at compile time and the other and runtime. This type of error could occur, for example,
if you have multiple versions of third party libraries pathed in.
|
— |