Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java try finally variations

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:

  1. InterruptedException (e.g. via Thread#interrupt()) or OutOfMemoryError exception is thrown
  2. JVM exits (e.g. via kill, System.exit())
  3. Hardware fail (or bug in JVM for complete list :)

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.

like image 315
Petr Gladkikh Avatar asked Apr 28 '10 06:04

Petr Gladkikh


People also ask

Can we use try and finally?

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.

How many finally blocks can a try block have?

A try block can have many catch blocks but only one finally block.

Can we put try catch in 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.

Can we write try without finally?

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.


1 Answers

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.

like image 184
Stephen C Avatar answered Sep 21 '22 03:09

Stephen C