Can I omit try-catch? - java

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.

Related

Will try-with-resources always close the resources

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.

Where should I put close() method?

In the following code, where should the close locate? Should it be in the try clause or in finally? If it is finally, should it be enclosed with another try-catch? Thanks.
PrintWriter out = null;
try {
out = new PrintWriter(
new BufferedWriter(
new FileWriter("out.txt", true)));
out.println("the text");
} catch (IOException e) {
System.err.println(e);
} finally {
if (out != null) {
out.close();
}
}
See the documentation for try-with-resources. If you're using at least Java 7, there's a nice syntax for this. Otherwise, the finally block is appropriate, since it should be closed in both the normal and exceptional cases.
Put it in the finally block.
Because you should close the Writer in either case (exception or no exception).
To handle close properly, one should ensure that it gets called whether or not an exception occurs in the main-line code, but one should also ensure that if close gets called following an exception in the main-line and then throws an exception itself, it won't cause the main-line exception to be discarded; depending upon various factors including whether the object was open for reading or writing, it may be desirable to either let the main-line exception percolate up (perhaps encapsulating information about the close failure), log or encapsulate the main-line exception but have the close failure percolate up, or throw a "double fault" exception which encapsulates both of the others.
The try-with-resources feature of Java 7 provides pretty good behavior for many scenarios: if an exception occurs in try and another in close, the latter exceptions get added to a list of suppressed exceptions (which exception-handling code should look for). If a method is supposed to grab data from a wireless sensor and write it to a file, and if the caller will expect that in the event of sensor trouble the file will hold as much information as was read successfully, then a failure to close the file may be more important than a sensor failure [if the sensor e.g. only includes "return oldest item" and "delete oldest item" commands, then if the file closed properly an exception during sensor communication would mean that any data which was no longer in the sensor would be in the file. If the file didn't close properly, that would imply that there might have been permanent data loss, and someone should be told about it.
Code to handle the "sensor capture" scenario would end up being a bit icky: the sensor read logic would be placed within a try block whose finally would capture any exception to a variable. The finally block would then have to use its own try block for the close; if an exception occurs there, throw a custom writeFileCloseFailure exception which encapsulates both the exception (if any) from the try block and the exception from the close; otherwise, rethrow the exception (if any) from the try block. Note that since ioException could represent either a failure to get data from the sensor (somewhat expected and tolerable) or a failure to write the file (very bad), wrapping in another exception type would allow the caller to distinguish those conditions.

Are streams closed automatically on error?

Hi all I understand that if we read bytes from an InputStream and we have finished reading all the bytes (or we do not intend to read to the end of stream), we must call close() to release system resources associated with the stream.
Now I was wondering if I read bytes and it throws a java.io.IOException, am I still required to call close() to release system resources associated with the stream?
Or is it true that on errors, streams are closed automatically so we do not have to call close() ?
The OS itself might close the streams and deallocate resources because the process (namely, the JVM) terminates, but it is not mandated to do so.
You should always implement a finally block where you close it in cases like these, e.g. like this:
InputStream is = null;
try {
is = new FileInputStream(new File("lolwtf"));
//read stuff here
} catch (IOException e) {
System.out.println("omfg, it didn't work");
} finally {
is.close();
}
This isn't really guaranteed to work if it threw in the first place, but you'll probably wanna terminate at that point anyway since your data source is probably messed up in some way. You can find out more info about it if you keep the InputStream's provider around, like, if I kept a ref to the File object around in my example, I could check whether it exists etc via File's interface, but that's specific to your particular data provider.
This tactic gets more useful with network sessions that throw, e.g., with Hibernate...

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 I need to close a ByteArrayInputStream?

Short question,
I saw in some old code where a ByteArrayInputStream was created like:
new BufferedReader(new InputStreamReader(new ByteArrayInputStream(somebytes)));
And then the BufferedReader is used to read out somebytes line by line.
All working fine, but I noticed that the BufferedReader is never closed.
This is all working in a long running websphere application, the somebytes are not terrible big (200k most), it is only invoked a few times a week and we're not experiencing any apparent memory leaks. So I expect that all the objects are successfully garbage collected.
I always (once) learned that input/output streams need to be closed, in a finally statement. Are ByteStreams the exception to this rule?
kind regards
Jeroen.
You don't have to close ByteArrayInputStream, the moment it is not referenced by any variable, garbage collector will release the stream and somebytes (of course assuming they aren't referenced somewhere else).
However it is always a good practice to close every stream, in fact, maybe the implementation creating the stream will change in the future and instead of raw bytes you'll be reading file? Also static code analyzing tools like PMD or FindBugs (see comments) will most likely complain.
If you are bored with closing the stream and being forced to handle impossible IOException, you might use IOUtils:
IOUtils.closeQuietly(stream);
It is always good practice to close your readers. However not closing a ByteArrayInputStream does not have as heavy of a potential negative effect because you are not accessing a file, just a byte array in memory.
As #TomaszNurkiewicz mentioned it's always good to close the opened stream. Another good way to let it do the try block itself. Use try with resource like.......
try ( InputStream inputStream = new ByteArrayInputStream(bytes); Workbook workBook = new XSSFWorkbook(inputStream)) {
here Workbook and InputStream both implements Closeable Interface so once try block completes ( normally or abruptly), stream will be closed for sure.
Resources need to be closed in a finally (or equivalent). But where you just have some bytes, no it doesn't matter. Although when writing, be careful to flush in the happy case.

Categories

Resources