Java Exceptions
This article is an analysis of the following: Java Exception Design, what Java exception can tell, and how to use Java Exceptions
Join the DZone community and get the full member experience.
Join For FreeJava Exception
Java Exception is a class created to handle abnormal application behavior. In this article, I'll explain how to use the Java Exception class and how to create your exception structure considering the existing Java Exceptions design. Java exception notion is one of the critical milestones in java and every developer must know it.
Java Exception Structure Is More Informative Than You Think
Java Exceptions have a structure that is pretty informative and can tell the developer a set of important things (if the developer uses this structure properly). So, here, you can see the basic structure:
The main parent that can catch all possible situations is Throwable which has 2 children: Error and Exception.
Java Error
Java Error case stands for abnormal situations. Once an Error appears application will be likely shut down.
Java Exception
Java Exceptions, unlike Error, have a chance to recover an application from a problem and try to keep the application up. Exceptions also split into 2 groups:
Exceptions are represented by Runtime and Not Runtime exceptions, also known as checked exceptions. This classification is pretty similar to Error Exceptions but, in that division, the Checked exception is more optimistic in terms of recovery.
Checked and Unchecked Exceptions
In Java, there are 2 types of exceptions. Checked exceptions force developers to create handler exceptions or rethrown them. If a checked exception is rethrown, then the java function has to declare it in its signature. Unchecked exception unline checked doesn't require any handling. Such design meant that unchecked exceptions can't be handled and are doomed to be thrown up to the top parent.
Exception Handling in Java
There are two ways to process exceptions thrown: Handle it inside the current method or just rethrow it. There is no better way to do it; you might have one parent handler or handle it somehow, e.g. make retry logic.
Good, Bad, Ugly
After the introduction, we can split all exceptions into 3 groups: Checked, Runtime, and Error. The main idea is that each of them would be thrown into different situations. The most optimistical is a Checked exception. The Runtime would belong to a situation with a small chance of recovery. And, the most pessimistic is Error.
Checked, Runtime, Error; So What?
Knowing the type of exception class we can potentially answer on next questions:
- How bad the situation is and what the cause of the problem is.
- How to fix the problem.
- Do we need to restart JVM?
- Do we need to rewrite the code?
Knowing the exception class we can predict what possibly went wrong. Thinking over the potential cause we can assume what was the cause of the problem and how to fix it. Let's review the most popular scenarios and find out what those exceptions can tell us. In the next paragraphs, we review famous exceptions and investigate what was the potential code. In our investigation, we assume that the application is stable enough and the development stage has been completed and tested.
Investigating Error Exceptions
We begin from the most pessimistical case or our Ugly Guy. Is Error really that ugly? Let's take a look into the most popular Java Errors:
Potential Cause | How likely Cause is | How to fix | Need to rewrite code? | Need restart JVM? | |
OutOfMemory | Application ate all memory | High | Increase heap memory size | NO | YES |
Memory leak | Low | Find memory leak and fix | YES | YES | |
StackOverFlow | Not enough memory in Stack | High | Increase Stack memory size | NO | YES |
Infinity Recursion | Low | Set a limit for recursion calls | YES | YES | |
NoClassDefFoundError | Missing dependency | High | Add dependency or fix dependency configuration | NO | YES |
Failed to load class during initialization | Low | Change initialization process | YES | YES |
So, in most cases, all you need to do is change JVM config or add the missing dependency. There are still cases that require code changes, but they are less likely in order to apply changes in every situation.
Investigating Checked Exceptions
For checked exceptions, we expect that there is a chance to recover the problem; for example, try again. In this part, we review the most famous Checked exceptions. Provided exceptions might be parent for each other, but, here, I list just most popular cases regardless of their relationship:
Potential Cause | How likely Cause is | How to fix | Need to rewrite code? | Need to restart? | |
FileNotFoundException | The file doesn’t exist | High | Create file | No | No |
Application call for the wrong path | Low | Fix wrong path generation | Yes | Yes | |
IOException | Access to resources is invalid | High | Make resources available again | No | No |
ClassNotFoundException | The class wasn't added in dependency | High | Add missing dependency | No | Yes |
Implementation calls the wrong class | Medium | Change class call | Yes | Yes | |
SqlException | Schema doesn't match to query | High | Apply missing script to database | No | No |
Mistake in query | Low | Change the query | Yes | Yes | |
Connection refused | High | Turn database on, change the port | No | No | |
InterruptedException | Dependent thread notified about interruption (lock released, another thread completed the operation) | High | There is no need to fix it; it's a way to notify about events in the dependent thread | No | No |
Another thread became broken and notified related using interrupt | Medium | Fix problem appeared in another thread (can be anything) | Yes | Yes | |
SocketException | Port is taken | High | Open/Release the port | No | No |
Server dropped connection | High | Check network connection or make | No | No |
Okkaay, so a lot of exceptions, but, as I promised, I put here the most popular exceptions. So, what does this table say? If we take a look into the most likely causes we will find out that most of them not just don't require any code changes but not even an application restart. So, obviously, Checked exceptions deserve to be Good Guy.
Investigating Runtime Exceptions
The most common and personally the most pessimistic exception: Runtime. Checked and Error exceptions error don't lead to any code changes. But, Runtime exceptions in most of the cases highlight real problems in the code that can't be fixed without rewriting the code. Let's find out why by reviewing the most popular Runtime exceptions:
Potential Cause | How likely Cause is | How to fix | Need to rewrite code? | Need to restart? | |
NullPointerException | The expected non-nullable object was null | High | Add validation layer before calling | YES | YES |
Some resource wasn't available and returned null data instead | Medium | Add validation layer before calling | YES | YES | |
ConcurrentModificationException | The collection has been changed during iteration | High | Make collection iteration and modification separately | YES | YES |
The collection has been changed from another thread during iteration | High | Add synchronization for collection | YES | YES | |
IlliegalArgumentException | Passed parameter is invalid | High | Add validation before passing param | YES | YES |
NumberFormatException | The passed parameter has the wrong format or wrong symbol | High | Add format or remove invisible symbols before passing data | YES | YES |
ArrayIndexOutOfBoundsException | Instruction tried to access to cell by non-existent index | High | Change accessing logic to the proper one | YES | YES |
NoSuchElementException | Access to element been when pointer already changed the position | High | Change accessing logic to the proper one | YES | YES |
The collection has been modified during the iteration | High | Add synchronization for collection | YES | YES |
An example might make an impression that any Runtime exception makes the application doomed. In most cases, it's correct because the application can't be recovered without code changes. Eventually, the Runtime exception is our Bad Guy which leads to new code changes, developer's stress, and business losses.
A Bit of Criticism
During this review, we made one heavy assumption: the code is production-ready and well-tested. But, in practice, it's hardly achievable. So, the conclusions we did are not 100% reliable, but the more the code is stable, the more realistic our conclusions are.
Checked Exceptions and Code Pollution
Each Checked Exception brings with it 3 lines of extra code. As a consequence code becames polluted. Such code is less readable and pretty ugle, it's one of the most known Java disadvantage.
Personally I prefer Unchecked exceptions. Even if I desing a library I can describe all potential exception that my API can thrown. So users of such library can consider their code desing even with unchecked exceptions. So shortly how I see checked exceptions:
Opinions expressed by DZone contributors are their own.
Comments