When a running Java application fails, it creates an exception object encapsulating the error condition and throws it back to the running code. The executing program can now introspect the exception object, which is simply a Java object, to analyse the cause of the exception and take a corrective action. If no corrective action is taken, the program may terminate abnormally. In a multithreaded program, the thread that generated the unhandled exception may terminate while the other threads in the application continue running.
Errors may be classified as:
The fatal errors are the ones that need to be terminated when the application cannot continue to function properly. These are sometimes also called hard errors. A typical example of this type of error is OutOfMemoryError. This is a serious problem, and application recovery in such a situation may not be viable. Generally, these types of fatal errors are thrown by the methods of the Java API—or by the Java Virtual Machine itself.
The other types of errors, known as non-fatal, may not be so serious, and application recovery in most cases is possible. As examples of this type of error condition, consider the case where our application tries to open a file. If the file is not locatable, the application will allow us to re-enter the filename, along with the appropriate path, and reattempt to open the file. If the file is corrupted, the program may give us an opportunity to open another copy or to open an altogether different file. Consider another example: When we open a website in our browser, if the site is currently unavailable, the browser allows us to open another site. One more example: If an application is performing some mathematical computation on some input data and the data is out of range, the application detects the condition during computation and allows us to re-enter the data before performing the computations one more time.
In all these cases, the error conditions do not cause the application to terminate. These are aptly called non-fatal errors. They occur in a running application, and a corrective measure is taken to prevent an application crash. There is another class of non-fatal errors that occur due to mistakes made by a programmer. For example, a NullPointerException is a typical error that is generated by error-ridden application code.
The Non-fatal Errors
As we just learned, non-fatal errors are generally caused by inherent mistakes made by programmers. We typically call these mistakes program bugs. Whatever we do, these non-fatal errors or exceptions will always occur in our application—and when we least expect them. Fortunately, Java provides a mechanism to take preventive action against such unforeseen errors. Before I discuss this mechanism, let’s first look at why such errors occur in the first place and why it is necessary to catch them. Consider an installer for a new software application. This new software may depend on some other software for its operation. For example, installing NetBeans requires that Java SE be preinstalled on our machines. The NetBeans installer therefore looks for Java SE on the machine where NetBeans is being installed. After searching the default directories, if it does not find Java SE, it raises an exception, prompting the user to specify the Java installation folder. If this error is not processed as indicated, the installer will terminate. By providing the error handler, the installer application gives the user an opportunity to try another folder. Consider another example: software that monitors the cabin pressure in an airplane. When the cabin pressure drops below a predetermined threshold, the oxygen masks automatically drop down. The drop in cabin pressure generates an exception, which is then processed gracefully, thus saving us from an application crash (perhaps even an airplane crash) and providing us with needed oxygen.