Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / August 2007

Tip: Looking for answers? Try searching our database.

what's the point in finally?

Thread view: 
Crouchez - 07 Aug 2007 13:19 GMT
try{
   //blah    }
   catch(Exception ex){
     //    }
   finally{    //do something    }why not justtry{//blah}catch(Exception
e){}//do something
bugbear - 07 Aug 2007 13:32 GMT
> try{
>     //blah    }
>     catch(Exception ex){
>       //    }
>     finally{    //do something    }why not justtry{//blah}catch(Exception
> e){}//do something

What if your exception handling code throws an Exception?

  BugBear
Michael Jung - 07 Aug 2007 13:47 GMT
> > try{
> >     //blah    }
[quoted text clipped - 4 lines]
>
> What if your exception handling code throws an Exception?

In fact, if you throw an exception in the finally block you have a much
toughre problem at hand. finally is used, e.g., to free resources in the good
and the bad case. Or implement some code that should be executed regardless of
whether you want the caller to get an exception or not.

Consider try blocks without catch but with finally or whithout finally but
catch.

Michael
Eric Sosman - 07 Aug 2007 13:47 GMT
> try{
>     //blah    }
>     catch(Exception ex){
>       //    }
>     finally{    //do something    }why not justtry{//blah}catch(Exception
> e){}//do something

    For one thing, the finally clause will execute no matter
how the try-ed code terminates: By throwing an Exception, by
throwing some other kind of Throwable, by return-ing or by
break-ing or by running all the way to its end -- the code
in the finally clause will be executed regardless.

    Another point is that it is almost always wrong to catch
Exception: You should catch IOException or InterruptedException
or some other, more specific kind of condition (or conditions).
The code in a catch clause is supposed to "deal with" the
exceptional condition, which means you need to have anticipated
the possibility and written code expressly for that outcome.  It's
just not possible to "deal" effectively with every possible kind
of Throwable, so it's pretty much a given that some kinds of
Throwable will not be caught.  Would you like your cleanup code
to execute anyhow?  Then put it in the finally clause.

    Still another issue: Once you catch an Exception, that's the
end of the line; Java's processing of it ceases once it's caught.
So what do you do if you'd like to clean up "en passant" but
let the original Exception propagate outward to your caller?
You could re-throw the same Exception after cleaning up, or
you could wrap the caught Exception in a new Exception of your
own and throw that one instead, but both courses are clumsy.
(The second is sometimes forced upon you for other reasons.)
Put your cleanup code in the finally clause and you get exactly
the desired effect without the extra running around.

Signature

Eric Sosman
esosman@ieee-dot-org.invalid

Roedy Green - 07 Aug 2007 14:06 GMT
what if you throw an exception you DON'T catch?
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Crouchez - 07 Aug 2007 14:07 GMT
Scenario A

try{
  //blah
}
catch(Exception e){
}
finally{
  //do something
}

why not just...

Scenario B

try{
  //blah
}catch(Exception e){
}
 //do something

OK right. I'm not following the arguments here. The //do something will
always be called in both scenarios unless something isn't returned in the
catch method? I don't understand why there is more use of resources either
in Scenario B? So what's the use of finally?
Patricia Shanahan - 07 Aug 2007 14:30 GMT
> Scenario A
>
[quoted text clipped - 21 lines]
> catch method? I don't understand why there is more use of resources either
> in Scenario B? So what's the use of finally?

In the second scenario //do something will not be called if, for
example, there was a stack overflow, because StackOverflowError does not
extend Exception.

Also consider the case in which //blah contains a return statement. Code
immediately after the try-catch-finally will not get executed. The
finally block will.

Second, catching and hiding Exception is such a dangerous thing to do
that I don't really care whether finally is or is not needed in such
code. I'm much more interested in:

try{
  // blah
}
catch(SomeException e){
  // Do something about it
}
catch(AnotherException e){
  // Do something else
}
finally{
  // Clean up after blah
}

In this, much more realistic, case there may be exceptions that do not
get caught, and with non-trivial catch blocks the catch blocks
themselves may return or throw exceptions of their own. As before, none
of the errors are being caught, and blah may contain a return statement.

Most of the very, very few gotos I wrote when I was programming in C
were substitutes for finally - situations in which there were a lot of
logical returns, but some clean-up code that had to be run on the way
out, regardless of why the function was finishing.

Patricia
Crouchez - 07 Aug 2007 15:53 GMT
>> Scenario A
>>
[quoted text clipped - 25 lines]
> example, there was a stack overflow, because StackOverflowError does not
> extend Exception.

are you sure? whether code throws an exception/error/throwable or not it
will still get to //do something in both scenarios. With StackOverflowError
or OutofMemoryError then the program often stops completely.

> Also consider the case in which //blah contains a return statement. Code
> immediately after the try-catch-finally will not get executed. The
> finally block will.

Ahh i see this point. I thought return was the ultimate last in the chain -
finally does indeed get called before return but i can't think of any reason
to do that.
Crouchez - 07 Aug 2007 16:10 GMT
>>> Scenario A
>>>
[quoted text clipped - 38 lines]
> chain - finally does indeed get called before return but i can't think of
> any reason to do that.

you're right with the StackOverflowError or OutofMemoryError thing - finally
does get called. Cheers for that
Patricia Shanahan - 07 Aug 2007 16:15 GMT
>>> Scenario A
>>>
[quoted text clipped - 28 lines]
> will still get to //do something in both scenarios. With StackOverflowError
> or OutofMemoryError then the program often stops completely.

I am sure. This program:

public class StackOverflowTest {
  public static void main(String[] args) {
    try {
      try {
        badRecursion();
      } catch (Exception e) {
        System.out.println("Exception caught");
      } finally {
        System.out.println("In finally block");
      }
      System.out.println("After try-catch-finally");
    } catch (StackOverflowError e) {
      System.out.println("Caught " + e);
    }
  }
  static void badRecursion() {
    badRecursion();
  }
}

prints:

In finally block
Caught java.lang.StackOverflowError

It does not reach the "After try-catch-finally" printout.

In many cases a program could in theory continue after an Error, but it
is usually not a good idea. Error implies that something is VERY wrong.

>> Also consider the case in which //blah contains a return statement. Code
>> immediately after the try-catch-finally will not get executed. The
[quoted text clipped - 3 lines]
> finally does indeed get called before return but i can't think of any reason
> to do that.

finally allows you to write return statements where they logically
belong and yet be sure the method's clean-up code runs.

When I saw try-catch-finally, I knew I would not miss "goto". The few
goto's I wrote in C were all emulating a finally structure, making sure
that no matter how I completed a function I would do the cleanup.

Patricia
bugbear - 07 Aug 2007 16:21 GMT
>> Also consider the case in which //blah contains a return statement. Code
>> immediately after the try-catch-finally will not get executed. The
[quoted text clipped - 3 lines]
> finally does indeed get called before return but i can't think of any reason
> to do that.

I suggest you go back and read Patricia's comments (and code)
after she says "I'm much more interested in: "

It's good stuff, and will help you.

  BugBear
Daniel Pitts - 07 Aug 2007 17:08 GMT
On Aug 7, 7:53 am, "Crouchez" <b...@bllllllahblllbllahblahblahhh.com>
wrote:

> >> Scenario A
>
[quoted text clipped - 37 lines]
> finally does indeed get called before return but i can't think of any reason
> to do that.

One typical use case:
try {
  return parseSomeXml();
} catch (ParserException e) {
  throw new MyGenericException("Can parse xml", e);
} catch (IOException e) {
  throw new MyGenericException("IO problem loading XML", e);
} finally {
 cleanUpStuff();
}
Thomas Hawtin - 07 Aug 2007 17:45 GMT
> One typical use case:
> try {
[quoted text clipped - 6 lines]
>   cleanUpStuff();
> }

The trouble is that cleanUpStuff is usually declared to throw an
exception. Therefore code like that is often incorrect or messy.

My guess is that the evolution of Java went something like:

 o Start with C++ where resources are flushed explicitly and destructor
do not throw. If you throw an exception from a destructor and the
destructor is called due to an exception unwinding the stack then, IIRC,
abort is called which by default calls terminate.

 o This makes try-catch-finally relatively natural. I believe catch
(...) logically comes after catches with explicit exception types in
C++. I guess catch-before-finally can also allow the exception object to
depend upon the resource still being open (though generally a poor idea).

 o Java goes in for virtual methods and decorators. Unfortunately
"ownership" of the resource is moved into the decorator (this would make
sense if the "decorator" create the resource from a factory rather than
being passed through the constructor).

 o In order to support such decorators (buffered output streams for
example), all resources can throw exceptions when being closed. Closing
an input stream is a classic example where a close declares that it
throws an exception, but probably shouldn't.

 o We are now in a situation where finally needs to be inside the try
block, but the syntax is the wrong way around.

There is also the problem that the finally block will need a reference
to the resource, even though the construction of the resource needs to
be within the try-catch.

So the general pattern should be:

   try {
       acquire-resource;
       try {
           decorate-resource;
           use-decorator;
           flush-decorator;
       } finally {
           release-resource;
       }
   } catch (ResourceException exc) {
       ... erm, do something sensible ...
       ... probably wrap in a different exception ...
   }

Now, if the exception makes sense for the method to throw, the catch can
be removed.

With closures, such as methods within anonymous inner classes, the
common code can be factored out (although with the current syntax, you
will still end up with some highly verbose boilerplate).

Tom Hawtin
kaldrenon - 08 Aug 2007 19:19 GMT
On Aug 7, 10:53 am, "Crouchez" <b...@bllllllahblllbllahblahblahhh.com>
wrote:
> are you sure? whether code throws an exception/error/throwable or not it
> will still get to //do something in both scenarios. With StackOverflowError
> or OutofMemoryError then the program often stops completely.

public class Test
{
   public static void main(String[] args)
   {
    try
    {
       return;
    }
    catch(Exception e){}
    finally
    {
       System.out.println("testing");
    }
   }
}

Output:
"testing"
Crouchez - 09 Aug 2007 00:14 GMT
> On Aug 7, 10:53 am, "Crouchez" <b...@bllllllahblllbllahblahblahhh.com>
> wrote:
[quoted text clipped - 21 lines]
> Output:
> "testing"

yeah i only figured that after i did a test
bugbear - 07 Aug 2007 16:12 GMT
> Scenario A
>
[quoted text clipped - 21 lines]
> catch method? I don't understand why there is more use of resources either
> in Scenario B? So what's the use of finally?

In your code there is no point in finally. If you had REAL exception handling,
i.e. non empty exception blocks (which you should), the distinction
may become more obvious.

  BugBear
Crouchez - 08 Aug 2007 19:10 GMT
So...

You can't actually catch or code in a contigency plan for an
OutofMemoryError but with finally you can? because finally runs regardless
of whether an exception or error is caught or not? ie. finally always runs
if the JVM is?
Lew - 08 Aug 2007 23:13 GMT
> You can't actually catch or code in a contigency [sic] plan for an
> OutofMemoryError but with finally you can? because finally runs regardless
> of whether an exception or error is caught or not? ie. [sic] finally always runs
> if the JVM is?

Not correct.  You can catch Errors and /try/ to do something about them *in
the catch block*, just like any other Throwable.  The finally block is not the
place to handle such things; the catch block is.

That said, the reason you can't effectively catch an Error is that it
represents a situation so fubared that there is no effective recovery
available.  Still, you can declare a catch block to attempt to minimize the
damage.

Signature

Lew

Twisted - 09 Aug 2007 00:12 GMT
> That said, the reason you can't effectively catch an Error is that it
> represents a situation so fubared that there is no effective recovery
> available.  Still, you can declare a catch block to attempt to minimize the
> damage.

Curiously, I'd say that StackOverflowError, at minimum, may be an
exception to this rule. I can imagine e.g.

public int myMethod (int arg) {
   if (isBaseCase(arg)) return 0;
   try {
       return recursiveMyMethod(arg);
   } catch (StackOverflowError e) {
       throw new IllegalArgumentException("Argument " + arg + " to
myMethod is too big.");
   }
}

The stack unwind "undoes" the damage of a stack overflow, since the
stack ends up as stubby as it was before the recursive call. Of course
the caller might still just upchuck on the IllegalArgumentException.
It's not hard to imagine a less efficient nonrecursive version of
myMethod being called, though, or some other such recovery depending
on the situation, or the result of the IAE being a particular user
operation failing without the whole app bombing.

In multithreaded parallelized code, another way to "recover" from even
OOME is to let it kill the thread it arises within. Another thread
goes to allocate something and this forces a GC, which reclaims all
the resources the now-dead thread held. Memory pressure thus leads to
scaled-back parallelization. With a control thread that holds the job
queues and has some ability to detect worker thread disappearance,
jobs can be reissued. Performance degrades instead of the task
bombing. A factory can attempt to recreate the missing worker threads
after some time has elapsed. A "fat job" could cause half the threads
to die but eventually be done with and the system would bounce back up
to its usual performance after a while.

Ultimately, how recoverable or irrecoverable any of these are is
dependent on the requirements and details of what's being implemented.

Certainly typical applications with user documents need to catch all
of them, including and especially OOME, and do a panic-save of the
user's session and unsaved data to where the next session will attempt
to recover, at minimum. (Not over the original files in case of data
corruption or other inconsistent transitional states caused by the
interrupting throwable!) To be able to do this, the exception handler
can trigger a graceful but non-memory-allocating shutdown that tells
threads to quit, destroys displayed UI, and drops references to most
objects other than those representing unsaved data, then call
System.gc() (though this should probably not be necessary), then
create some streams and save the unsaved data to the recovery file,
then pop up an apologetic error message, before shutting down. The
memory freed by first disposing of the previously-visible UI objects
alone is probably sufficient to do this successfully during exit.
Wojtek - 08 Aug 2007 19:41 GMT
Crouchez wrote :
> try{
>     //blah    }
>     catch(Exception ex){
>       //    }
>     finally{    //do something    }why not justtry{//blah}catch(Exception
> e){}//do something

public void myMethod() throws MyException
{
 try
 {
   grabSomeResources();
   somethingDangerous();  // throws MyException
 }
 finally
 {
   freeSomeResources();
 }
}

In the above the resources will always be freed.

Signature

Wojtek :-)

Thomas Hawtin - 08 Aug 2007 20:21 GMT
>  try
>  {
[quoted text clipped - 8 lines]
>
> In the above the resources will always be freed.

Even if it fails to be acquired!

The basic standard form is:

   acquire; try { use; } finally { release; }.

Tom Hawtin
steve - 13 Aug 2007 00:26 GMT
> try{
>     //blah    }
>     catch(Exception ex){
>       //    }
>     finally{    //do something    }why not justtry{//blah}catch(Exception
> e){}//do something

finally IS ALWAYS CALLED.

Exception is not
Joshua Cranmer - 14 Aug 2007 00:16 GMT
> finally IS ALWAYS CALLED.
>
> Exception is not

From Peter Norvig's Java IAQ (Infrequently Answered Questions):

Q: Finally is always called, right?
A:

public class Foo {
     public static void main(String[] args) {
         try {
             System.exit(0);
         } finally {
             System.out.println("Oi!");
         }
     }
}

I suppose the best way to phrase that is "A finally block is always
called except if the VM is in a highly abnormal, unrecoverable state
(e.g., SIGKILL) or ceases to exist in the middle of the referent try
block (catch block if one is executed)." ^C'ing an infinite loop also
classifies as an abnormal, unrecoverable state, as does deadlocks.

Signature

Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

bugbear - 14 Aug 2007 16:37 GMT
>> finally IS ALWAYS CALLED.
>>
[quoted text clipped - 20 lines]
> block (catch block if one is executed)." ^C'ing an infinite loop also
> classifies as an abnormal, unrecoverable state, as does deadlocks.

I guess the a pickaxe through the CPU die would also
prevent "finally" being called.

I don't normally worry about such things when coding :-)

   BugBear
manivannan.palanichamy@gmail.com - 15 Aug 2007 05:47 GMT
On Aug 7, 5:19 pm, "Crouchez" <b...@bllllllahblllbllahblahblahhh.com>
wrote:
> try{
>     //blah    }
>     catch(Exception ex){
>       //    }
>     finally{    //do something    }why not justtry{//blah}catch(Exception
> e){}//do something

try
{
//do task1
}
catch(Exception e)
{
handle exception()
}
// do task2

Assume that you need to execute task1. Irrespective of the task1's
success or failure, you need to execute task3. In the above case, no
prob, you dont need to put finally block. task3 will be always
executed though task1 succeeds/fails. Because catch block handles
'Exception', which is the root class of exception hierarchy. So, the
catch block will catch all Exception.

But, look at this code,

try
{
//task1
}
catch(CustomException e)
{
}
finally
{
//task3
}

In this example, the catch block will handle only your
CustomException. Suppose, if any other exception is thrown (say
RuntimeException), then catch block cant handle it, so the execution
will break, and task3 will not be executed. Now, if you put the task3
code inside finally block, it will be always executed irrespective of
any exception.
Generally,
1. logging code will be put in finally block
2. resource free-up code like database connection release, file close
will be present in finally block
3. any acknowledgment message sending code can be placed in finally
block

--
Manivannan.Palanichamy (@) Oracle.com
http://mani.gw.googlepages.com/index.html


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.