This question nags me for a while but I did not found complete answer to it yet (e.g. this one is for C# Initializing disposable resources outside or inside try/finally). Consider two following Java code fragments:
Closeable in = new FileInputStream("data.txt");
try {
doSomething(in);
} finally {
in.close();
}
and second variation
Closeable in = null;
try {
in = new FileInputStream("data.txt");
doSomething(in);
} finally {
if (null != in) in.close();
}
The part that worries me is that the thread might be somewhat interrupted between the moment resource is acquired (e.g. file is opened) but resulting value is not assigned to respective local variable. Is there any other scenarios the thread might be interrupted in the point above other than:
I have read that second approach is somewhat more "idiomatic" but IMO in the scenario above there's no difference and in all other scenarios they are equal.
So the question:
What are the differences between the two? Which should I prefer if I do concerned about freeing resources (especially in heavily multi-threading applications)? Why?
I would appreciate if anyone points me to parts of Java/JVM specs that support the answers.
Generally try-finally is used to assure that some piece of code gets executed irrespective if the exception occurs or not. Catch block is generally missing because code in try block does not throw any checked exception which can be caught. This is a good point.
A try block can have many catch blocks but only one finally block.
The finally block contains the critical code that will execute regardless of whether the exception has occurred or not. Q #5) Can finally block have try-catch? Answer: Yes, if we have a cleanup code that might throw an exception in the finally block, then we can have a try-catch block.
Core Java bootcamp program with Hands on practiceYes, It is possible to have a try block without a catch block by using a final block. As we know, a final block will always execute even there is an exception occurred in a try block, except System. exit() it will execute always.
I don't think there is any reason to be concerned:
1) InterruptedException (e.g. via Thread#interrupt())
Calling Thread.interrupt()
does not cause InterruptedException
to be thrown spontaneously. The exception is only thrown within specific (and well documented) blocking methods; i.e. blocking I/O and synchronization methods. This exception cannot be thrown after returning from the stream constructor and before entering the try block.
or OutOfMemoryError exception is thrown
If an OutOfMemoryError
is thrown, you cannot guarantee full recovery of the underlying file descriptor, no matter where you put the stream constructor. You should never attempt to recover from an OOM, so the question of whether the stream is closed is moot. Besides, this exception is only thrown on a thread that is actually attempting to allocate memory, and that is not happening at this point.
2) JVM exits (e.g. via kill, System.exit())
If the application is being forcibly terminated by an external kill
or a System.exit()
call, it does not matter if streams are closed properly. Besides, in both cases there is no guarantee that finally clauses will be executed.
3) Hardware fail (or bug in JVM for complete list :)
All bets are off. You have no way of knowing if anything will execute, let alone the finally blocks.
There is one more situation where a thread might receive an spontaneous exception at that point, with some (naive) expectation that it might recover. That is when some misguided programmer decides to call the deprecated Thread.stop()
method. You might think that putting the stream constructor call inside the try
block would help. But actually it won't, because the ThreadDeath
exception could be raised inside the stream constructor between opening the underlying file and completing construction of the stream object. So the FD could leak anyway.
This is just one reason why Thread.stop()
is deprecated. Don't use it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With