Should java try blocks be scoped as tightly as possible? - java

I've been told that there is some overhead in using the Java try-catch mechanism. So, while it is necessary to put methods that throw checked exception within a try block to handle the possible exception, it is good practice performance-wise to limit the size of the try block to contain only those operations that could throw exceptions.
I'm not so sure that this is a sensible conclusion.
Consider the two implementations below of a function that processes a specified text file.
Even if it is true that the first one incurs some unnecessary overhead, I find it much easier to follow. It is less clear where exactly the exceptions come from just from looking at statements, but the comments clearly show which statements are responsible.
The second one is much longer and complicated than the first. In particular, the nice line-reading idiom of the first has to be mangled to fit the readLine call into a try block.
What is the best practice for handling exceptions in a funcion where multiple exceptions could be thrown in its definition?
This one contains all the processing code within the try block:
void processFile(File f)
{
try
{
// construction of FileReader can throw FileNotFoundException
BufferedReader in = new BufferedReader(new FileReader(f));
// call of readLine can throw IOException
String line;
while ((line = in.readLine()) != null)
{
process(line);
}
}
catch (FileNotFoundException ex)
{
handle(ex);
}
catch (IOException ex)
{
handle(ex);
}
}
This one contains only the methods that throw exceptions within try blocks:
void processFile(File f)
{
FileReader reader;
try
{
reader = new FileReader(f);
}
catch (FileNotFoundException ex)
{
handle(ex);
return;
}
BufferedReader in = new BufferedReader(reader);
String line;
while (true)
{
try
{
line = in.readLine();
}
catch (IOException ex)
{
handle(ex);
break;
}
if (line == null)
{
break;
}
process(line);
}
}

The basic premise here is false: the size of a try block makes no difference in performance. Performance is affected by actually raising exceptions at runtime, and that's independent of the size of the try block.
However, keeping try blocks small can lead to better programs.
You might catch exceptions to recover and proceed, or you might catch them simply to report them to the caller (or to a human, via some UI).
In the first case, failures from which you can recover are often very specific, and this leads to smaller try blocks.
In the second case, where an exception is caught so that it can be wrapped by another exception and re-thrown, or displayed to the user, small try blocks mean that you know more precisely which operation failed, and the higher-level context in which that call was made. This allows you to create more specific error reports.
Of course, there areā€¦ exceptions (sorry!) to these guidelines. For example, in some cases very specific error reports could be a security problem.
It might be useful to know what effect a try block has on the compiled code. It doesn't change the compiled instructions at all! (Of course, the corresponding catch block does, since it's like any other code.)
A try block creates an entry in the exception table associated with the method. This table has a range of source instructions counters, an exception type, and a destination instruction. When an exception is raised, this table is examined to see if there is an entry with a matching type, and a range that includes the instruction that raised the exception. If it does, execution branches to the corresponding destination number.
The important thing to realize is that this table isn't consulted (and has no effect on running performance) unless it's needed. (Neglecting a little overhead in the loading of the class.)

I've been told that there is some overhead in using the Java try-catch mechanism.
Absolutely. And there's overhead to method calls, too. But you shouldn't put all your code in one method.
Not to toot the premature optimization horn, but the focus should be on ease of reading, organization, etc. Language constructs rarely impact performance as much as system organization and choice of algorithms.
To me, the first is easiest to read.

No. The only thing that you should be considering is where you can reasonably handle the exception and what resources you need to reclaim (with finally).

This is premature optimization at its worst. Don't do it.
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil" - Knuth.

there is very very little benefit to the 2nd method. after all if you can successfully open a file but not read from it, then there is something very wrong with your computer. thus knowing that the io exception came from the readLine() method is very rarely useful. also as you know, different exceptions are thrown for different problems anyway (FileNotFoundException, etc)
as long as you scope it with a 'logical' block, ie opening, reading, and closing a file in 1 go, i would go with the first method. it's much simpler to read and, especially when dealing with IO, the processor cycles used by the try-catch overhead would be minimal if any.

Putting the try blocks around the specific code that may throw an exception, makes it, in my opinion easier to read. You're likely to want to display a different message for each error and provide instructions to the user, which will be different depending on where the error occurs.
However, the performance issue that most people refer to is related to raising the exception, not to the try block itself.
In other words, as long as you never have an error raised, the try block won't noticeably affect performance. You shouldn't consider a try block just another flow control construct and raise an error to branch through your code. That's what you want to avoid.

The second method will generate a compiler error that reader may not have been initialized. You can get around that by initializing it to null, but that just means you could get an NPE, and there's no advantage to that.

Related

When to consider catching Specific Exceptions Vs General Exception in Java

Catching specific exceptions like option 1 below is very common and also considered the save way to catch exceptions, Why the option 2 is rarely considered because of how verbose(not sure if that's the word to use!) it can become, that's what I understand so far.
My question is that are there any other instances when one should consider catching exceptions like option 2(General Exception) rather than Option 1 ?
Opt1 -> Specific Exceptions:
try{
TextIO.putf(s);
FileOutputStream mFileOutputStream = new FileOutputStream("/content/doc/test.pdf", true);
}catch (FileNotFoundException notfEx){
//Do something
}catch (NullPointerException nullEx){
//Do something
}catch(IllegalArgumentException illEx){
//Do something
}
Opt2 -> General Exception:
try{
TextIO.putf(s);
FileOutputStream mFileOutputStream = new FileOutputStream("/content/doc/test.pdf", true);
}catch (Exception ex){
if(ex.getClass() == java.io.FileNotFoundException.class) {
//Do something
}else if(ex.getClass() == java.lang.IllegalArgumentException.class){
//Do something
}else if(ex.getClass() == java.lang.NullPointerException.class){
//Do something
}
}
}
You are simply asking the wrong question, a typical example of pre-mature optimisation.
The (potentially nil) difference in performance between your two options does not matter at all.
Keep in mind: you are talking about dealing with an exception that was just thrown.
Rest assured: creating that exception, and collecting its stack trace is thousands of times more expensive compared to some hypothetical gain because of using your options 1 or 2.
Thus: you can safely ignore performance here. You simply do what is easier to read, and easier to understand for human readers of your code. Which of course dictates to use version 1. And as the comments are pointing out: actually, your option 2 isn't equivalent to option 1 (as it ignores sub classes of exceptions). So, not only is that option 2 way harder to read and maintain, it is also very likely to result in unexpected (wrong) exception handling.
Finally: you are also victim of another common problem with newbie Java programmers. They assume that "what you do in source java" is the relevant factor for java performance at runtime. But that is not true. The real performance of java comes out of the JIT, and its efforts to compile java byte code into machine code. You have to make sure that the JIT can do a good job (and of course: to avoid stupid mistakes within your code). So again: your ideas do not contribute anything meaningful to "how to achieve performance".

Java catch block, caught exception is not final

I am checking out the new features of Java SE7 and I am currently at this point:
http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
regarding the catch multiple feature, when I came across this statement:
Note: If a catch block handles more than one exception type, then the
catch parameter is implicitly final. In this example, the catch
parameter ex is final and therefore you cannot assign any values to it
within the catch block.
I never noticed that the caught exception is not final in the classic case of handleing caught exceptions.
I just wonder why is that a good thing in the first place? Would it not be ill-advised to essentially MODIFY a caught exception before I guess rethrowing it or maybe logging it's message? Should it not be up to the trowing mechanism to create the exception so it represents exactly what it should?
I have never seen an exception being modified in the catch block can maybe someone point out it's benefits?
It's pretty much the same as method arguments:
You usually don't modify them and many people agree that they should be treated as final (whether or not to actually write final in front of them is a matter of some debate).
But since there's no technical requirement that says it must be final, the language gives you the option to choose.
Personally I know of no good reason to modify the exception reference of a catch-block.
I cannot think of a convincing use-case for modifying an exception in a classic catch clause. However, that doesn't mean it should be forbidden. Especially given that you can modify a parameter variable. If you find this worrisome, you have the option of declaring the exception variable to be final.
On the other hand, allowing modification in the multi-exception catch would introduces the possibility of truly bizarre and confusing code such as this:
catch (IOException | NullPointerException ex) {
...
ex = new IllegalArgumentException(...);
}
I imagine that's what the designers had in mind when they added the restriction in this case.
But either way, this is how the Java language is defined, and what we have to live with. There's not a lot of point in debating the apparent inconsistencies ... unless you are intending to design and implement a new language.
The reason I can think of to enforce it final is due to performance. Once the catch evaluation starts, having a final immutable value in the mechanics of the evaluation ensures a faster evaluation of all catches. Since try-catch is extensively used throughout any java code, the highest performance design is preferable.
Based on the above, it implies a performance improvement that affects most programs.
The idea behind exception-based error handling is that each error should be recovered, if at all possible, at the appropriate level of abstraction. Such error recovery might require information that is not directly available where the exception is actually handled. For this reason it might be convenient to catch the exception, augment it with the relevant information and rethrow it or possibly set it as cause of a new exception object of a more appropriate class.

Factoring out the finally {...} block

I wonder if the following two swnippest are semantically identical, and, if not, what are the differences (we assume that we want to compute a result of type R, and want to guard against exception X that may be thrown in the course of doing so):
public R tcf(....) {
try {
R some = ...;
... compute the result ....
return some;
}
catch (X exception) {
... exception handling ....
}
finally {
... clean up ....
}
}
and the following:
public R tc(....) {
try {
R some = ...;
... compute the result ....
return some;
}
catch (X exception) {
... exception handling ....
}
}
public R tf(....) {
try {
return tc(....); // wrap the try-catch in tc()
}
finally {
... clean up ....
}
}
As far as I can see, it boils down to if a try-catch block wrapped in a try block with finally is the same, semantically, as a try-catch-finally block, assuming that the code in the finally and catch phrases stays the same and the outer try block just promotes the result of the inner one.
Practical relevance: Given a code base that does not make use of try-catch-finally, when it should, and given that for some reason, one cannot toch that code, one could more or less mechanically generate a layer of wrapper methods that add the finally.
I am fully aware of the fact, that for many reasons, one should use the try ... catch ... finally whenever possible. Specifically, I am not suggesting in any way that one should refactor the first example so that it looks like the second.
Rather, I want to make sure that example 2 can safely be refactored to example 1.
Functionally, they are equivalent.
I think it's good style to perform cleanup in the same method that has allocated the resources in question. In some cases this is the only practical way to go about things (for example, if the cleanup involves variables that are local to tcf/tc).
Also, if tc doesn't clean up after itself, the cleanup becomes part of the function's contract, as a caller's obligation. This makes the design more error-prone, since the cleanup is easy to forget or get wrong. Additionally, if the steps involved in the cleanup in any way change, every single caller would need to be tracked down and updated.
Bottom line: if the cleanup can be performed in tcf, it should be.
They are the same, however. The try/finally should always be right after the recourse (that finally releases) is claimed. (note that this happens just before the try)
For example:
getLock();
try {
doSomething()
}
finally {
releaseLock();
}
Because it is really easy to forget to clean up, it should always happen at the same location as the taking of the resource. Reason for this is that you should never burden your callers with something they always have to do (and you can do yourself)
Not performing the finally in the same method as the try/catch leaves you open to the method doing the try/catch at some point being called without the finally being executed, which is likely a bug.
I'd therefore not advise you to write it like that, though in the scenario you describe, having to add functionality through a finally when the method containing the try/catch can't be modified, it's the only way.
I think your description is pretty accurate in that the tf finally will execute in both cases and that the exception handling will be dealt with in either tcf or tf catch block.
That is, in example (1): if an exception occurs in your try, flow will execute your catch block followed by your finally block. In example (2), in tc, if an exception occurs in your try block, flow will continue in your catch block and then (presuming the exception isn't re-thrown) return to the calling line in tf. On completion of your tf try block, flow will continue in your tf finally block.
I guess the main implication to be aware of, and that you may not be able to correct in the way you suggest, is that:
If you implement your code as in your second example, you won't be able to necessarily access the tc resources from tf to be able to clean them up.
Even if you can, you're cleaning up resources at a layer that is not close to the resource usage and may not even be used by other client code of the framework. I guess that's a question of documentation and training.
Both are identical. but finally is used when you are having a risk of breaking the function in between or want to release some resources held by the function. in that case catch is skipped but finally will definitely execute.
try can be used either with catch or finally or both. finally generally can't show the exception occurred but catch can trace the exception.

Try-catch: is this acceptable practice?

We have received Java code from a software supplier. It contains a lot of try-catch blocks with nothing in the catch part. They're all over the place. Example:
try {
spaceBlock.enable(LindsayModel);
} catch (Exception e) {
}
My questions are: Is the above acceptable practice? If so, when? Or should I just go ahead and remove all of these "bogus" try and catch statements?
To me this looks like terrible practice, but I'm not experienced enough in Java to tell for sure. Why catch errors if you're not going to do anything with them? Seems to me, you would only do that if you were confident that an exception would be of absolutely no consequence and you don't care if one occurs. However, this is not really the case in our particular application.
EDIT To give some context: We bought a Java-scriptable product from the supplier. Alongside the product, they provided a large proof-of-concept script tailored to our needs. This script came "free of charge" (though we wouldn't have bought the product if it hadn't come with the script) and it "works". But the script is a real pain to build upon, due to many things that even I as a Java novice recognise as awful practice, one instance being this bogus try-catch business.
This is indeed terrible practice. Especially the catching of Exception rather than something specific gives off a horrible smell - even a NullPointerException will be swallowed. Even if it is assured that a particular thrown exception is of no real consequence, one should always log it at the very least:
try {
// code
}
catch (MyInconsequentialException mie) {
// tune level for this logger in logging config file if this is too spammy
MY_LOGGER.warning("Caught an inconsequential exception.", mie);
}
However it is unlikely an exception is completely meaningless in this situation. I recommend researching exactly what exception(s) the application's code is intending to swallow here, and what they would really mean for the execution.
One important distinction is whether the try/catches are used to swallow checked exceptions. If this is the case, it probably indicates extreme apathy on the programmer's part - somebody just wanted his/her code to compile. At the least, the code should be amended:
try {
// code
}
catch (SpecificCheckedException sce) {
// make sure there is exception logging done farther up
throw new RuntimeException(sce);
}
This will rethrow the exception wrapped in an unchecked RuntimeException, effectively allowing the code to compile. Even this can be considered a bandaid however - best practice for checked exceptions is to handle them on an individual basis, either in the current method or farther up by adding throws SpecificCheckedException to the method signature.
As #Tom Hawtin mentioned, new Error(sce) can be used instead of new RuntimeException(sce) in order to circumvent any additional Exception catches farther up, which makes sense for something that isn't expected to be thrown.
If the try/catch is not being used to swallow checked exceptions, it is equally dangerous and should simply be removed.
Terrible, indeed. Swallowing an exception like this can be dangerous. How will you know if something bad has happened?
I'd feel better if the vendor wrote comments to document and acknowledge it ("We know what we're doing"). I'd feel even better if there was a strategy apparent in the code to deal with the consequences. Wrap it in a RuntimeException and rethrow; set the return value to an appropriate value. Anything!
"All over the place"? Are there multiple try/catch blocks littering the code? Personally, I don't like that idiom. I prefer one per method.
Maybe you should find a new vendor or write your own.
try {
meshContinuum.enable(MeshingModel);
} catch (Exception e) {
}
This looks like unfinished code. If the enable method throws an Exception then it will be caught and swallowed by the code. If it doesn't then it does not make sense to try to catch a non occuring exception.
Check to see the methods and where their signatures are not followed by throws exceptionName, then remove the empty try-catch statements from the places they are called.
You can theoretically put try-catch around any statement. The compiler will not complain about it. It does not make sense though, since this way one may hide real exceptions.
You can see this as a sign of bad code quality. You should probably be prepared to run into problems of different type too.
It's not the best:
It hides evidence of the exception so debugging is harder
It may cause features to fail silently
It suggests that the author might actually have wanted to handle the exception but never got around to it
So, there may be cases where this is OK, such as an exception that really is of no consequence (the case that comes to mind is Python's mkdirs, which throws an exception if the directory already exists), but usually, it's not so great.
Unfortunately you cannot just remove it, because it the try block throws a checked exception then it will have to be declared in the throws clause of the method. The callers of the method will then have to catch it (but not if the callers also have this catch (Exception e) {} abomination).
As an alternative, consider replacing it with
try {
meshContinuum.enable(MeshingModel);
} catch (Exception e) {
throw (e instanceof RuntimeException) ? (RuntimeException) e : new RuntimeException(e);
}
Since RuntimeException (and classes that extend it) are unchecked exceptions they do not need to be declared in the throws clause.
What did your contract with the supplier specify? If what they wrote, bad practice and all, meets the spec then they will charge you for a rewrite.
Better to specify a set of tests that will enter many or all of those try-catch blocks and hence fail. If the tests fail you have a better argument to make them fix their terrible code.
Horrible idea on the face of it, totally depends on what you're actually calling. Usually it's done out of laziness or habituated bad practices.
Actually ... not so fast.
There are legitimate cases for ignoring an exception.
Suppose that an exception has happened already, and we're already in a catch(). While in the catch(), we want to make best effort to clean up (which could fail, too). Which exception to return?? The original one, of course. The code looks like this:
try {
something-that-throws();
} catch(Exception e) {
try {
something-else-that-throws();
} catch(Exception e1) {}
throw e;
}
When we really don't care whether an operation succeeds, but (unfortunately) the operation's author throws an exception if a failure occurs.
if (reinitialize) {
try {
FileUtils.forceDelete(sandboxFile); // delete directory if it's there
} catch(Exception e) {}
}
The above saves a rather tortured attempt to see if sandboxFile actually exists before deleting it anyway.

In Java how would you write the equivalent of Iterable which could throw exceptions?

In java a class can implement Iterable which lets you use the foreach() statement and the iteration syntatic sugar:
for(T t:ts) ...
However, this does not allow you to throw exceptions on the construction for an Iterator. If you were iterating off a network, file, database etc it would be nice to be able to throw exceptions. Obvious candidates are java.io.InputStream, Reader and the java.nio.Channel code, but none of this can use Generics like the Iterable interface can.
Is there a common idiom or Java API for this situation?
Clarification: This is asking if there is a pattern or alternative interface for iterating for objects off a non-memory source. As responders have said, just throwing RuntimeExceptions to get around the problem is not recommended or what I was looking for.
Edit 2: Thanks to answers so far. The consensus seems to be "you can't". So can I extend the question to "What do you do in this situation, when this situation would be useful?" Just write your own interface?
Unfortunately you can't. There are two problems:
The Iterator API doesn't declare any exceptions to be thrown, so you'd have to throw RuntimeExceptions (or non-Exception throwables)
The enhanced for loop doesn't do anything to try to release resources at the end of the loop
This is very annoying. In C#, for instance, you can really easily write code to iterate through the lines of a text file:
public static IEnumerable<string> ReadLines(string filename)
{
using (TextReader reader = File.OpenText(filename))
{
string line;
while ( (line=reader.ReadLine()) != null)
{
yield return line;
}
}
}
Use as:
foreach (string line in ReadLines("foo.txt"))
The foreach loop calls Dispose on the IEnumerator in a finally block, which translates to "check if we need to do anything in the iterator block's finally (from the using statement)". Obviously there are no checked exceptions in C#, so that side of things isn't a problem either.
A whole (useful!) idiom is pretty much unworkable in Java due to this.
Streams like a network aren't really iterable in the traditional sense. Data can come through at any time, so it doesn't make sense to have a for each loop.
For a file read, or a DB snapshot (like a select query) there's no reason you can't take that data, segment it into logical chunks and implement an iterable interface.
You can also call an initialize method first that will catch any exceptions, if that's an issue.
try{
ts.initializeIOIterator();
}catch(...)
for(T t:ts)
...
Best what you can do is to create RuntimeIOException which you will throw from your hasNext/next implementation in case of errors.
try {
for (...) {
// do my stuff here
}
catch (RuntimeIOException e) {
throw e.getCause(); // rethrow IOException
}
RuntimeIOException will be runtime exception, wrapping your IOException:
class RuntimeIOException extends RuntimeException {
RuntimeIOException(IOException e) {
super(e);
}
IOException getCause() {
return (IOException) super.getCause();
}
}
Sometimes there is no other way.
I'd say you can't, even if you could you probably shouldn't. You get bytes from these things, if they were used in a for loop likely every byte would end up boxed.
What you can do is wrap checked exceptions in unchecked exceptions and comply to the iterable interface, though again this isn't advisable.
Generally in this situation, I would throw an appropriate subclass of RuntimeException in the Iterable's implementation.
In terms of cleaning up resources, a try - finally block works just as well wrapping a foreach block as it does around any other bit of code, so from the client's perspective it can easily use this to clean up any resources. If you want to manage resources within the Iterable it can be trickier, since there's no obvious start and finish lifecycle points.
In this case the best you could probably do is to create the resources on demand (i.e. the first call to next()), and then destroy them either when a call to next() is about to return false, or when an exception is thrown in the body of next(). Doing this would of course mean that when your next() method exits with an exception, the iterator can no longer be used - this is not an unreasonable constraint to place (consider the exception a more error-y version of returning false) but is something you should document as this isn't strictly covered by the interface.
That said, the above assumes that you're creating something solely as an Iterable. I find that in practice, when I implement Iterable on a class, it's more like a "super-getter" (i.e. a way for clients to conveniently access the information stored within it), than it is the point of the class itself. Most of the time these objects will be set up independently and accessed via other methods, so their lifecycle can be managed completely separately from their existence as an Iterable.
This might seem tangential to the question, but the immediate answer to the question is straightforward ("use runtime exceptions") - the tricky part is maintaining an appropriate state in the presence of these exceptions.

Categories

Resources