Will try-with-resources always close the resources - java

Will try-with-resources always close the resource irrespective of error condition? I mean consider below code:
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
Will br always be closed? I have read Oracle documentation which says:
it will be closed regardless of whether the try statement completes normally or abruptly
So it will work whether program runs normally or throws exception. But what about conditions like System.exit or JVM crashes? I know these conditions won't work for finally block. So is there a condition at which try-with-resources fail?
This just I am asking for curiosity, can someone please shed light on this?

try-with-resource is just a syntactic sugar to save you the hassle of messing with a finally clause. Nothing "java-ish" that happens inside the try block would prevent the resource from closing - returning, throwing an exception, etc.
Anything that terminates the JVM abruptly (such as calling System#exit, killing the JVM's process, unplugging the computer, etc.) won't be handled, just as it's not handled by an old-fashioned finally clause.

If the VM terminates in any way any memory and file channels will be freed anyway. If you have custom code in the respective close operation and the VM crashes I expect that this code will not be run but that almost never happens. Most errors are handled by the VM and in any of that cases the close method will be called.

Related

Can I omit try-catch?

I want to fetch an HTML page and read in with BufferedReader. So I use try-with-resources to open it handles IOException this way:
try(BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) {
} catch(IOException e) {
throw e;
}
Is this a good pattern to catch and instantly throw? And what if I omit try at all and state that function throws IOException? If then any potentional memory leak?
Much appreciate any advice!
A catch block is not required in a try-with-resources statement. You could write the following, which would mean exactly the same as your original code:
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(url.openStream()))) {
// do something
}
So, you can leave out the catch block, if all you ever do there is immediately throw the same exception again.
You do want the try block however, so that the BufferedReader and underlying stream(s) are automatically closed at the end of the block.
Is this a good pattern to catch and instantly throw?
No, catching and immediately re-throwing the same exception does not add anything useful.
To add to #Jesper's excellent answer, you do want to include the try block so that the BufferedReader will be closed right away. If you don't do this, it'll eventually be closed when the object is garbage collected, so it isn't technically a resource leak in the sense that the resources would eventually be reclaimed; however, the "eventually" part is potentially problematic because there are no guarantees as to exactly when that'll happen. Thus, a bigger issue is whether this would create race conditions if it's using a resource that needs to be reused eventually.
I'm not very familiar with the implementation details of that exact class, so this is somewhat speculative, but one example of an issue you can run into with some classes that perform network calls if you fail to return resources to the operating system promptly is port exhaustion.
By way of another example, if you are modifying a file, the file could remain locked until the GC happens to release the file lock by cleaning up the relevant object.

In what cases can a statement.close throw exception? What does it mean for the connection?

Everywhere we see that the Statement.close() is 'handled' by eating up the exception that it throws. What are the cases where it can throw an exception in the first place? And what does it mean for the connection with which this statement was created?
In other words, when does statement.close() throw an exception and would the connection still be 'healthy' to be used for creating new statements?
Also, what happens if resultset.close() throws?
First, consider what the close() method might need to do, and what might cause an exception.
E.g. a PreparedStatement might have created a stored procedure, which needs to be deleted by the close() method. executeQuery() may have opened a cursor, which is used by the ResultSet, and close() needs to close that cursor.
Exception could of course be an internal error, but is most likely a communication error, preventing the close operation from succeeding.
So, what does that mean? It means that resources are not being explicitly cleaned up. Since your operation is already complete, it's generally ok to ignore those close() exceptions, since resources will be reclaimed eventually anyway.
However, since the cause is probably a communication error, the connection is likely broken, which means that you'll just get another exception on whatever you try next, making it even less likely that your handling of the close() exception matters.
To be safe, an exception means that something is wrong, and unless you examine the exception to understand how bad it is, you should abort whatever you're doing. A new connection should be established if you want to try again.
But, as already mentioned, ignoring close() exceptions aren't really a big issue. It may lead to resource leaks, but if the problem is bad, you're just going to get another exception on your next action anyway.
Simplest case for such an exception: the connection, that handled the statement is closed before you are trying to close the statement or if the statement was closed -somehow- already. speaking for jdbc, the connection should be healthy.
In general: As Peter stated, if the documentation of the driver does not contain any recommendations how to handle such an exception, you can only log or debug it. maybe you could re-establish the connection to be sure it is healthy.
When you close a statement, a lot of things can happen. These basic things can happen when closing a statement:
The open result set - if any - is closed, which may require communication to the database
The statement handle on the database server is released, which requires communication to the database
Given this involves communication to the database, all kinds of errors can occur: file system errors, network connection problems, etc. These may be safe to ignore, but could also indicated something very wrong with your application or database.
A secondary effect of a statement close can be a transaction completion (a commit or rollback). This could - for example - happen in auto-commit mode when you execute a data-modifying statement that produces a result set: the transaction ends when the result set is closed by the close of the statement. If this transaction commit fails, and you ignore it, your application may have just had a data-loss event (because the data was not persisted), and you just went ahead and ignored it.
In other words: you should not just ignore or swallow exceptions from Statement.close() unless you are absolutely sure there will be no detrimental effects. At minimum log them so you can trace them in your logs (and maybe define alerts on the number of exceptions logged), but always consider if you need to wrap them in application-specific exceptions and throw them higher up the call chain for handling, or - for commit failures - if you need to retry anything.

Is it meaningful for AutoCloseable's close method to throw an exception? How should this be handled?

In C#, it is considered bad practice to throw exceptions in the Dispose method of an IDisposable.
By contrast, in java the close method of AutoCloseable allows any Exception whatsoever to be thrown and forces the caller to handle it somehow. But what is the caller reasonably expected to do if this happens? This suggests that the attempt to close the resource failed somehow. So does the user have to try to close the resource again before continuing, perhaps with some sort of exponential backoff?
The design of AutoCloseable is a result of Java's checked exceptions. Some implementations simply have to be able to throw checked exceptions, and so throws Exception is needed. However, implementations should declare more specific types thrown (if any):
While this interface method is declared to throw Exception, implementers are strongly encouraged to declare concrete implementations of the close method to throw more specific exceptions, or to throw no exception at all if the close operation cannot fail.
You shouldn't throw exceptions if there's a way of avoiding it, but you can't always avoid it. For example, when closing a BufferedOutputStream with unflushed data, the buffered stream has two options; ignoring the unwritten data and close, or writing it to the stream, which can cause exceptions to be thrown.
Because Java's designers were able to see the issues that arose with cleanup-exception handling in .NET's using blocks before implementing their own try-with-resources feature, they were able to improve upon it. In .NET, the author of a Dispose block is often faced with an unpleasant choice between swallowing any exceptions which occur, thus erroneously letting the calling program believe everything is fine, or letting exceptions percolating out from Dispose in such fashion as to obliterating any evidence of any previous exception. Fortunately, Java avoids that issue.
If a try-with-resources block succeeds normally and the close also succeeds normally, then the outside code sees everything as normal. If an exception occurs in the try portion but the close succeeds normally, the outside code will see the try-block exception. If the try completes normally but the close throws, the outside code will see the close exception. And if try throws, but close also throws, then outside code will see the try exception but also be able to retrieve any exception that occurred within close (and if multiple nested try-with-resources throw exceptions during close, all thrown exceptions will be available to the outside code).
Consequently, unlike the .NET design which often compels authors to stifle some potentially-serious exceptions thrown by Dispose, Java's design favors having close throw an exception any time something goes sufficiently wrong that the caller shouldn't be allowed to believe that everything's fine.
It looks like every operation involving the resources, including the implicit close() invocation, is considered part of the try{} block. Even thought technically/syntactically, the resources are mentioned outside the {} braces.
Meaning that if an IOException gets thrown during the close(), it will get caught by some catch() clause associated with your try (or it will propagate up).
About the reason why exceptions might need to be thrown : close() might cause flush(), flush() might cause write()s, and write()s might fail.

Why do I need to use finally to close resources?

Most of the time, the only thing I see a finally block used for is something like
FileInputStream f;
try{
f= new FileInputStream("sample.txt");
//something that uses f and sometimes throws an exception
}
catch(IOException ex){
/* Handle it somehow */
}
finally{
f.close();
}
My question is, if f's scope ends with the enclosing block, why do we need to close it in the finally?
Because garbage collection is not the same thing as resource cleanup.
For example, if you have a JDBC Connection object that goes out of scope, there's no signal sent to the database server to indicate that open cursors and connections are no longer needed. Without those messages, you'll eventually exhaust the number of cursors and connections available to you.
Same with file handles and any other resource. Clean up after thyself.
Well you've given a bad example - I suspect you meant something like FileInputStream - but the basic reason is that Java doesn't have deterministic finalization.
The scope of the variable f ends with the block it's declared in (not the try block), but that doesn't mean there are necessarily no "live" references to the object any more - and the garbage collector will neither finalize the object nor garbage collect it in any deterministic manner.
Unless you want to leave resources hanging around for an arbitrary length of time (and delay garbage collection, as finalizers require an extra round of collection before the memory is finally released), you should explicitly close resources.
Basically Java does not support RAII in the same way that C++ does; you shouldn't try to use it as if it were C++.
because finally is called everytime, even if you get an exception raised. the finally block insure you that the file/connection will be closed.
The reason is that Java doesn't guarantee that an object will be garbage-collected as soon as a particular reference to it falls out of scope. So for objects that reference limited system resources, such as a file descriptor, it's not enough to wait for garbage collection.
Note though, that java.io.File is not actually such an object.
We handled exception by try catch finally ,finally block every time execute but there is no guarantee of catch because catch block execute only if exception passed in parameter matched.
For example if we have open any database connection so it is must we closed it before leave,tht must be implemented into finally.

Do you really need the 'finally' block

There are 3 permutations of a try...catch...finally block in java.
try...catch
try...catch...finally
try...finally
Once the finally block is executed, control goes to the next line after the finally block. If I remove the finally block and move all its statements to the line after the try...catch block, would that have the same effect as having them in the finally block?
I know this is a very old question but I came across today and I was confused by the answers given. I mean, they are all correct but all answer on a theoretical or even philosophical level when there is a very straightforward practical answer to this question.
If you put a return, break, continue or any other java keyword that changes the sequential execution of code inside the catch block (or even try block), the statements inside the finally block will still be executed.
For example:
public void myFunc() {
double p = 1.0D;
String str = "bla";
try{
p = Double.valueOf(str);
}
catch(Exception ex){
System.out.println("Exception Happened");
return; //return statement here!!!
}finally{
System.out.println("Finally");
}
System.out.println("After finally");
}
when executed this code will print:
Exception Happened
Finally
That is the most important reason for the existence of a finally block. Most answers imply it or refer to it on the sidelines but none of them is putting emphasis on it. I think because this is kind of a newbie question such a straightforward answer is very important.
I think willcode comes the closest to expressing the key point here, and probably everyone means it but are not clear.
The problem is there is indeed something very wrong with what you are asking: "If i write all the statements after catch block instead of writing them into finally block then then would there be anything wrong?"
If you write all the statements after the catch block, what you are implying is that
1) You will always catch the exception.
2) You will always continue on to the next statements after you catch the exception.
This implies that you will always continue the execution "normally" after an exception, which is generally something you never in fact want to do.
Exceptions should be just that - exceptional. If you can in fact handle an exception, it is always better to write your code to consider those conditions first and not lead to an exception at all. If you follow this model then exceptions are truly exceptional - conditions you could not anticipate or at most not fix. Really not anticipate is what you should work towards. This means in general you are unable to handle true exceptions, which also means you should not just continue execution, often you end the application instead.
What is normally done is you allow an error to propagate back up the call stack. Some say this is done on the off chance that someone higher up in the chain may be able to handle it. I would say that essentially never happens, there are two real purposes to do this. One it may be something the user can fix, if there is one. So you propagate the error back up until you get to where you can report it to the user. Or two, a user cannot fix it but you want to get the entire call stack for debugging. Then you catch it at the top to fail gracefully.
The finally block now should have more meaning to you. As everyone says it always runs. The clearest use of a finally is really in a try... finally block. What you are now saying is if the code runs fine, great. We still need to do some clean up and the finally always executes then we move on. But if an exception occurs, we now really need that finally block because we may still need to do some clean up, but we are no longer catching the exception here so we are not going to be moving on anymore. The finally block is essential to ensure that clean up occurs.
The idea of an exception always halting execution may be hard for someone to grasp until they have a certain amount of experience, but that is in fact the way to always do things. If an error happened, either it was so minor you should have accounted for it to begin with, or else there are just more and more errors waiting to happen down the line.
"Swallowing" errors - catching them and moving on is the worst thing you can do because your program becomes unpredictable and you cannot find and fix bugs.
Well written code will contain as many try ... finally blocks as are necessary to make sure that resources are always released no matter the outcome. But well written code generally contain only a small number of try ... catch blocks that exist primarily to allow an application to fail as gracefully as possible, or defer to the user, which means at least always pass a message to the user etc. But you usually do not just catch an error and keep going.
The highlight is that a finally block is guaranteed to be executed even if an exception is raised and not caught. You then use the finally block, as a one time chance, to perform necessary clean-up like closing streams. The code after the finally block might never be reached.
From the java tutorial
The finally block always executes when
the try block exits. This ensures that
the finally block is executed even if
an unexpected exception occurs. But
finally is useful for more than just
exception handling — it allows the
programmer to avoid having cleanup
code accidentally bypassed by a
return, continue, or break. Putting
cleanup code in a finally block is
always a good practice, even when no
exceptions are anticipated.
If I understand the question, you're asking what's the difference between:
try {
Foo f = new Foo();
f.bar();
}
finally
{
Foo.baz();
}
And:
// This doesn't actually compile because a try block needs a catch and/or finally block
try {
Foo f = new Foo();
f.bar();
}
Foo.baz();
Or, more likely:
Foo f = new Foo();
f.bar();
Foo.baz();
The difference is that if either new Foo() or f.bar() throw an exception, the finally block will get executed in the first case, but that Foo.baz() won't get executed in the last two cases: instead control will skip over Foo.baz() while the JVM looks for an exception handler.
EDIT
Responding to your comment, what about:
Foo f = new Foo();
try {
f.bar();
}
catch (Exception ex)
{
// ...
}
f.baz();
You are right that, assuming the catch block doesn't rethrow the exception, or return from the method indicating a failure occured, then f.baz() gets called regardless of whether there was an exception. Even in that case, however, the finally block serves as documentation that f.baz() is used for cleanup.
More importantly, the fact that an exception was thrown usually is important, so it's very hard to write code that continues on doing whatever it was doing without knowing that an exception was thrown. There are times that exceptions indicate silly things that you can ignore, and in that case you should swallow the exception. More often, however, you will want to signal failure, either by rethrowing the exception (or throwing a different exception) or returning from the method with an error code.
For example, if f.bar() is supposed to convert a String to a Double, and on failure it throws a NumberFormatException, then code after the try block probably needs to know that the String was not actually converted to a Double. And, so, in general you won't want to continue after the catch block. Instead, you'll want to signal failure. This is known as "abort on failure" (compared to "resume on failure," which probably should be called "muddle on after failure with your fingers crossed").
Except, in special cases you may be able to muddle on. For instance, the catch block could set the relevant Double to Double.NaN which is designed specifically to propagate errors correctly in math expressions. Even in that case, the finally block serves as documentation that f.baz() is involved in some kind of cleanup.
The finally block contains lines of code that should be executed regardless whether an exception has been caught or not. Even if you decide to stop code running in that method. So code after the t-c-f might not be executed, but the finally code is "guaranteed" (guaranteed in the sense of a non crashing immediately breaking non handleable error).
Yes, there would be something very critically wrong.
And that is, your code would only run if there is an error.
Statements inside finally always run, regardless of an exception being thrown. That is the point.
finally block especially used at the time of exception prevention. If any runtime error occurs, the program may lead to terminate. So at this time, it will call finally block before going to terminate the program. Usually 'finally' contains connection closing statements, save operations and file input, output close operations.
If your code never throws exception, or you are consuming all exception that will be correct. That is not what always happens.
The question was indeed answered here (how to use finally)
My understanding of the answer is: there would be circumstances in which we would throw some exception that the except block won't be able to handle. What do you do in that situation? You wanna move on? Not a great idea! You better print something that indicates that you passed through a stage where an exception may or may not have occurred, if the exception occurred it should have been handled by the catch statement and if it was not handled, there may be some unmatched exception

Categories

Resources