To try-catch or not? What every Java Developer must know about Exceptions

Exceptions remain one of the most misunderstood and misused aspects of the Java programming language. This article will describe the absolute bare minimum, every Java developer must understand about Exceptions.

Exceptions are shorthand for exceptional conditions which disrupt the normal program flow. What happens in the background when an exception is thrown is that the control is transferred to the run-time system (JVM) which finds the appropriate handler and transfers control to it.

In Java, exceptional conditions come in three flavours, all of which are descendants of the Throwable class:

  1. Exception (widely know as Checked Exception)
  2. RuntimeException
  3. Error

The only difference between these, in terms of enforcement by the language, is that checked exceptions must be caught. In order words, the caller of a method that throws one or more checked exceptions must use the catch clause to handle the exceptions. The RuntimeException & Error classes are not subjected to this requirement.

I mentioned that all three flavours extend the Throwable class. Any object of this class could be thrown and subsequently caught, in the try-catch clause. This means a developer can freely throw any one of Exception, RuntimeException and Error as he or she likes.

Luckily, while there is a single concrete difference between the three flavours (the catch requirement), there are several guidelines and general rules which describe when it is appropriate to use which type of flavour. They are described below:

Exception (aka Checked Exception)

Checked exception must be caught and as such they force the programmer to deal with exceptional condition. It is a signal that something didn’t go as intended along with some information about what went wrong, and that “someone” should do something about it. In this sense, checked exceptions are for exceptional conditions that could be recovered from (e.g. car’s dashboard indicating that the battery needs servicing and won’t start).

According to official documentation:

These are exceptional conditions that a well-written application should anticipate and recover from. For example, suppose an application prompts a user for an input file name,  [..] But sometimes the user supplies the name of a nonexistent file, and the constructor throws java.io.FileNotFoundException. A well-written program will catch this exception and notify the user of the mistake, possibly prompting for a corrected file name.

Source: The Java Tutorials

RuntimeException

RuntimeExceptions are used to indicate programming errors, most commonly violation of some established contract. They make it impossible to continue further execution.

For example, the contract says that the array index mustn’t go past array length – 1. If you do it, bam, you get a RuntimeException. A real world analogy would be pumping diesel into a gasoline car: the unwritten contract says that you must not do it. There are no  signals, just the white smoke before the car comes to a grinding halt after a while. The message: it was your fault and could’ve been prevented by being smarter in the first place.

These are exceptional conditions that are internal to the application, and that the application usually cannot anticipate or recover from. These usually indicate programming bugs, such as logic errors or improper use of an API.

Source: The Java Tutorials

Error

These exceptional circumstances are like “act-of-god” events. Going back to our previous analogy, if a large scale alien invasion were to happen, there is nothing you could do your protect your car, or yourself (unless your last name is Ripley). In Software world, this amounts to the disk dying while you are in the process of reading a file from it. The bottom line is that you should not design your program to handle Errors since something has gone wrong in the grand scheme of things that are beyond your control.

These are exceptional conditions that are external to the application, and that the application usually cannot anticipate or recover from. For example, suppose that an application successfully opens a file for input, but is unable to read the file because of a hardware or system malfunction.

Source: The Java Tutorials

Not a Mathematician’s World 

Like many other things, the distinction between exceptional conditions, especially, Checked Exceptions and RuntimeExceptions isn’t so black and white. The rule says that if exceptional condition could be recovered from, use Checked Exception otherwise RuntimeException. However, most of the time, it depends on the judgement of the developer whether the situation is recoverable or not. As an example, suppose you are writing to a disk and the disk is full. If the developer determines that the situation could be recovered from, e.g., by clearing up some temporary files, checked exception should be used. If nothing could be done, RuntimeExceptions fits the bill.

Should you be catching Runtime Exceptions?

What’s the point of catching RuntimeExceptions if the condition is irrecoverable? The official recommendation from Oracle:

The application can catch this exception, but it probably makes more sense to eliminate the bug that caused the exception to occur.

Dividing a number by 0 will generate a run time exception, ArithmeticException, which according to our previous arguments, is not required to be caught. If you follow the Oracle’s advice, you would modify your program to check the arguments for division function and make sure that the denominator > 0. If it is not, we can halt further execution or even dare to throw a exception of our own: IllegalArgumentException.

In this case, the program got away by verifying the input parameters instead of catching RuntimeExceptions.

So when is it OK for an application to catch RuntimeExceptions?

A while back, I architected a high-performance traffic director with the goal of operating in the proximity of 10,000 transactions per seconds (TPS). The project had a very high availability criteria and one of the requirement was that it “must-never-exit”.

The director performs minimum amount of processing on each transaction before passing it further. Transactions came in two flavours, call them: A and B. We were only interested in transactions of type A. We had a transactions handler to process type A. Naturally, it “choked” run time exceptions when we passed in transactions of type B. The solution? Create a function and pass it every single transaction. If it returned true, we continued to further processing. Otherwise, we simply ignored the transaction, and continued onto the next one.

boolean checkFormat(Transaction t) {
//return true if the t is of type A. false otherwise.
}

This worked well, except…..

… the analysis showed that this function returned false only once a year. The reason, 99.99999999999999% transactions were of type A. Yet, we were subjecting every single transaction to be checked. This does not sound so bad, but due to the nature of transactions, the only way to differentiate was by doing expensive String comparison on various fields.

When this finding was brought to my knowledge, I immediately had the `checkFormat(…)` function removed and instead let the handler do it’s course and throw RuntimeException upon encountering transaction of type, B. When the exception gets thrown once a year, we catch it, log it and move onto the next transaction. The result: improvement in performance, and room to squeeze in additional calculations.

Summary

We saw that exceptions in Java come in three flavour. There aren’t any hard and fast rules to distinct between the flavours, a good design could be achieved by following general rules and guidelines.

Although, we can get away by not catching RuntimeExceptions most of the time, there are definitely some circumstances which justify catching these types of exceptions.

About these ads
About

I'm Umer Mansoor , the author of this blog.

Tagged with: ,
Posted in Java
27 comments on “To try-catch or not? What every Java Developer must know about Exceptions
  1. Anonymous says:

    What did I just waste my time on?

    • Cory Gross says:

      Did you read the entire article… I thought it was rather useful insight, particularly at the end. If you already knew all of this, did you not realize that before reading the entire thing?

  2. Cayman says:

    Good post. OutOfMemory is another RuntimeEcxeption that should be caught in high availability applications invoking garbage collector for clean up.

  3. traxtech says:

    And that’s just one example amongst thousands of others :(
    javax.xml.ws.WebServiceException is also quite commonly annoying.

  4. pjungwir says:

    I think it’s normal to catch RuntimeExceptions at a high level in your outer loop so you can log it, email it, or whatever, and not let your process die. This is what servlet containers like Tomcat are doing. I agree that catching them elsewhere raises suspicions.
    The author’s example seems fine, provided they can distinguish an exception-from-a-B-transaction vs an exception-from-a-program-bug. If I were him, I’d keep that checkFormat method, but only call it when I catch a RuntimeException, to see if it’s something to worry about or not.
    I was pleased that the author appears to have tested the performance of both approaches and is making a decision based on real numbers.

  5. You can invoke GC (which generally speaking, you should not), but this doesn’t guarantee it will clean up anything. OOM exceptions should be considered terminal, as they are an Error, not an Exception.

  6. aardvark179 says:

    I strongly agree that runtime exceptions are the right way to go for certain rare events, see for example the new Java 8 addExact and multiplyExact methods which throw exceptions on overflows. These will not happen often but making them an exception allows implementers of languages with numeric type promotion to remove their own checks, and for the JIT to optimise the entire exception away in most cases.

  7. stickfigure says:

    Sorry, this is not going to be gentle.
    This post is clearly written by someone who is new to Java, and starts with the antique assumption that the runtime/checked exception dichotomy is a good idea. After nearly two decades of experience, programmers and language designers have resoundingly voted this language design feature to be a failure. A little bit of experience catching idiotic exceptions like UnsupportedEncodingException and you start to see why. But it goes deeper than just bad design in the standard libraries – checked exceptions fundamentally violate interface encapsulation – try throwing a meaningful exception through Runnable or Iterator. The net result is stacktraces with dozens of wrapped exceptions that destroy any hope of meaningfully handling known error conditions.
    Stop it. JUST STOP IT. Checked exceptions have wasted hundreds of hours of my time, not just writing lame wrappers so that I don’t have to type try/catch on every line of code, but also by making debugging and error handling five times more painful than it should be.
    If you’re still touting checked exceptions in 2013, you are part of the problem. Stop it. Java needs to evolve, and your fresh-from-1995 opinion is not helping.
    TL;DR: Of course you should catch RuntimeExceptions. There should be no other kind of exception.

    • pifflesnort says:

      > checked exceptions fundamentally violate interface encapsulation
      You have that backwards. Unchecked exceptions will blithely and without warning completely explode your stack. They’re the Atomic Goto.
      The only way to know whether you’re going to get one is to check the documentation, where you can only hope that the API author — and the author of every API he calls — has actually documented the exceptions that get thrown, because the compiler will be no help whatsoever, and god forbid an API start throwing an exception later.
      > … try throwing a meaningful exception through Runnable or Iterator.
      If you pass around an object that conforms to Iterator, but throw an exception within it, __YOU’RE BREAKING THE API CONTRACT.__
      Anyone that relies on the API contract of the Iterator class could have their state completely walloped by the Atomic Goto you inserted with a runtime exception.
      > Stop it. JUST STOP IT. Checked exceptions have wasted hundreds of hours of my time, not just writing lame wrappers so that I don’t have to type try/catch on every line of code, but also by making debugging and error handling five times more painful than it should be.
      This makes no sense, because more work is required without checked exceptions.
      Without checked exceptions:
      – You must check the API docs for every line of code you write to see if it will throw an exception, and if so, what types.
      – If it throws an exception, you must either add a try/catch block to handle the error appropriately (or wrap it in a new exception type), or you must add documentation to your method to declare that it will bubble up an exception, and of what type.
      – If new exception types are thrown by underlying code, nothing tells you until your application explodes.
      With checked exceptions:
      – The compiler tells you what exceptions code throws, and of what type.
      – If it throws an exception, you must either add a try/catch block to handle the error appropriately, or declare it in the method prototype. The IDE will do both of these things for you.
      – If new exception types are thrown by underlying code, the compiler will warn you.
      > If you’re still touting checked exceptions in 2013, you are part of the problem. Stop it. Java needs to evolve, and your fresh-from-1995 opinion is not helping.
      Stop advocating broken API design and ignorance of API invariants.

    • Teckla says:

      “This post is clearly written by someone who is new to Java”
      That was uncalled for. But, since you’ve decided to immediately call into question people’s credentials, let me start with mine. I’ve done a little over 30 years of software development, and in that time I’ve programmed in no less than three assembly languages, several BASICs, Pascal, C, C++, JavaScript, dabbled with C#, dabbled with Go, dabbled with Python, been subjected to some Perl and PHP, etc. I’m not God’s Gift to Software Development, but I think I have enough experience that my opinion on this matter shouldn’t be discarded as uninformed.
      “and starts with the antique assumption that the runtime/checked exception dichotomy is a good idea.”
      I hope you’re aware that you’re begging the question. In any case, I think checked exceptions are fantastic.
      1. The “burden” of dealing with them is minuscule, especially when using modern IDEs. It takes just a few clicks or key presses to add try/catch blocks or re-throw exceptions as necessary. You don’t even have to waste time looking up documentation (which may be wrong or even nonexistent). Your tool-chain (IDE and compiler) handles the mundane details for you.
      2. It forces developers, who are often hurried, and who often make mistakes, to think about things that could go wrong, and deal with them (one way or another). Oh, sure, you see plenty of “catch (Exception e)” style abuses, but that particular “code smell” is so strong (i.e., easily identified) that it can make code reviews (personal and public) easier. Code reviews in languages with only unchecked exceptions are much more difficult and time consuming.
      3. Checked exceptions speeds development. Much less time is spent reading and re-reading API documentation to make sure you’ve caught all the possible exceptions that might be thrown (so that you can do things like produce meaningful error messages or log entries based on the exception thrown).
      4. Unchecked exceptions are a production run-time nightmare. My anecdotal but extensive experience is that languages with only unchecked exceptions cause far too many costly (in both time and money) production headaches. Never, ever defer until run-time, errors that can be caught at compile-time! Admittedly, it could be that my application domain colors my opinion here (I work on large systems, not small systems).
      The best argument I’ve heard against checked exceptions is that they “bloat the code”. It’s true: checked exceptions requires more code. But I’m writing code, not poetry. My job is to get the implementation right (which checked exceptions help me do) and to write reliable and robust software. Developers who put more emphasis on writing pretty code (sorry, “highly expressive”) might want to consider becoming artists instead, where they can fashion “pretty” creations to their heart’s content.

  8. laksjdf says:

    i want my 12 volts!!

  9. jhdevos says:

    Of course, there are also the RuntimeExceptions that should really have been just Exceptions. These are often thrown by libraries where new features required exceptions to be thrown, but they couldn’t be checked exceptions because the interface had to remain backwards compatible…
    Or, of course, libraries written by people who just don’t like checked exceptions at all.

  10. Grant says:

    Java is flawed by design. I feel sorry for people who are still using it. There are much better alternatives like .NET.

    • Grant says:

      Not to mention it is slow as hell. I can only imagine the pain the author had to go through to write a java program for handling “10,000 transactions per seconds”!

      • 10kloc says:

        >> Not to mention it is slow as hell.
        Not necessarily. In most cases, the code can be optimized by the compiler to be on par with C/C++ code or even faster. The “stop-the-world” garbage collectors do cause slight performance trade-offs, but coming from a C++ background, I would much rather have automatic garbage collection than code reviewing and code reviewing to discover and eliminate all memory leakages. While processors are not doubling their speeds every 18 months, computers are still getting faster and faster. Even if your argument was true, I’m willing to take a slight performance hit over flexibility.

        >> pain the author had to go through to write a java program for handling “10,000 transactions per seconds”!

        Useless and ambiguous argument. Which stage of the software development are you referring to: architecting, coding, production? I find architecting and writing Java is fun. Not to mention the plethora of well tested libraries and frameworks which ship with JDK make my life easier.

        Thanks for posting.

      • david says:

        “Java is flawed by design. I feel sorry for people who are still using it. There are much better alternatives like .NET. Not to mention it is slow as hell.”

        Obvious troll is obvious!

    • GrantISARETARD says:

      Grant you are a retarded loser. It’s .NET that’s flawed. Still clinging to exes, dlls and com components. LOL like it’s 1990.

  11. Smoyer says:

    I’d love to be able to say I never have to catch RuntimeExceptions, but that would require that library and framework writers actually use checked exceptions when they should. The best example I can think of (and one that a JEE developer who uses JPA should be intimately familiar with) is that that the getSingleResult() method of the Query object in JPA throws RuntimeExceptions if zero or more than one result is returned.

    • Suresh says:

      The funny thing is, in almost any discussion about exception handling in Java, I hear the opposite complaint – too many APIs throw checked exceptions. I’ve been leaning more and more to liking it when APIs force consumers to at least be aware of known error conditions.
      Scala’s Option type is another example of this – I’ve watched people be sort of annoyed by it at first, but it tends to really improve the reliability and overall quality of the code when it is used properly.

      • lucian1900 says:

        Scala’s Option is a monad, so it’s very easy to chain several actions and safely decide if they all succeeded or failed. It doesn’t compare with checked exceptions at all.

  12. Uchikoma says:

    Runtime exceptions can turn into ugly production problems. I prefer a combination of Validation, Success/Failure, Some/None and checked exceptions.
    Runtime exceptions can turn into ugly production problems. I prefer a combination of Validation, Success/Failure, Some/None and checked exceptions.

  13. Ajinkya says:

    Before reading full article, I thought another blah-blah but after reading it I can say, it does offer some insight. In real world there are many situation,when you want to catch RuntimeException.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: