• Post Reply Bookmark Topic Watch Topic
  • New Topic

try catch block and variable scope  RSS feed

 
Tom Griffith
Ranch Hand
Posts: 275
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello. If anybody has a minute, this is roughly what is giving me a problem...

//OUTER TRY BLOCK
try{
PreparedStatement statement=null;

} catch (Exception e) {
statement.close();

} finally {
statement.close();
}


In case of error on the try, I want to close 'statement' because there would be the potential for jvm memory problems leaving 'statement' out there (this is all in a larger recursive loop)...however the catch and finally cannot recognize the variable 'statement'. I always thought any variable declared within try would be within scope of catch and finally but i guess thats not the case.

On the other hand, I apparently need to initialize 'statement' within the try because if I move the initialization outside the try to get the variable 'statement' within scope of everything, i get 'variable may not be initialized' error on the statement.close() in the catch and finally.

Does anybody have any ideas where i can ensure 'statement' can be closed from the outer catch or finally? Thank you very much.
[ July 28, 2008: Message edited by: Tom Griffith ]
 
Joanne Neal
Rancher
Posts: 3742
16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Move the initialisation outside of the outer try and initialise it to null. Before calling close in your finally block, check that statement is not null.
You can also remove the statement.close() from your catch block. The finally block will always be run* whether an exception is thrown or not.



* It is possible to stop the finally block being run if an exception is thrown, but you've no need to worry about that at the moment.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The scope ends when the enclosing brackets are closed. So the scope will not be seen in the catch or finally. To do this you have to move the declaration out of the try block (and you only need to close in the finally, it gets called if either the case of normal execution or an exception.




Originally posted by Tom Griffith:
Hello. If anybody has a minute, this is roughly what is giving me a problem...

//OUTER TRY BLOCK
try{
PreparedStatement statement=null;

} catch (Exception e) {
statement.close();

} finally {
statement.close();
}


In case of error on the try, I want to close 'statement' because there would be the potential for jvm memory problems, but the catch and finally cannot recognize the variable 'statement'. I always thought any variable declared within try would be within scope of catch and finally but i guess thats not the case.

On the other hand, I need to initialize statement within the try because if I move the initialization outside the outer try, i get 'variable may not be initialized' error on the close() statements in the outer catch and finally. Catch-22.

Does anybody have any ideas where i can ensure 'statement' can be closed from the outer catch or finally? Thank you very much.

[ July 28, 2008: Message edited by: Tom Griffith ]
 
Tom Griffith
Ranch Hand
Posts: 275
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you very much for the replies, they were both extremely helpful. I had to do some tweaking becasue the code has nested try-catches but i think I have it. i was getting a nullpointerexception on the statement.close() in finally but as i also read here, I had to check it for a null value first because I null it out inside an inner try.
 
Tom Griffith
Ranch Hand
Posts: 275
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hello. if anybody has a minute, I actually i have a follow-up question on this...

statement=null;

and

statement.close();

do not have the same impact on the jvm memory, right? Simply setting statement to null still leaves the object in the heap while close() removes it, is that right? I am concerned becasue to avoid a nullpointerexception, I threw in the following if...

if (statement!=null) {
statement.remove();
}

but I think I'd still want to remove the statement object, even if set to null, right?..however, I wouldn't be sure how to call remove() without throwing a nullpointer in that case...thank you very much again...
[ July 28, 2008: Message edited by: Tom Griffith ]
 
Joanne Neal
Rancher
Posts: 3742
16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
statement is not an object, it is a reference to an object. If you set it to null, then it means that it no longer references any object. The object it previously referenced may at this point become eligible for garbage collection if there are no other references to it.

Calling the close method does not affect the object in memory - it simply releases all the database resources associated with the object. After calling close the object will still be in memory and will remain there until there are no more references to it. This will happen either when all references are set to null or they go out of scope.

It is recommended that you call the close method as soon as you are finished with it. To do this you need a reference to the object, so you have to do it before setting the reference to null.
 
Tom Griffith
Ranch Hand
Posts: 275
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thank you again for the input...i think what i'm fishing for is a condition in the finally that checks if a prepared statement had 'remove()' called on it rather than if the reference is currently null...i'm just real freaked about runaway preparedstatements that somehow didn't get removed due to an exception sucking up memory. I do call remove() as soon as the code is donw with the sql operation but SQL itself may toss an exception...
[ July 28, 2008: Message edited by: Tom Griffith ]
 
Tom Griffith
Ranch Hand
Posts: 275
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
i think i'm just going to reuse the 'statement' variable and only set it to null at the very beginning during initialization..then call remove() on 'statement' after each sql op and in the finally. This way the old objects 'statement' pointed to should be garbage collected and the statement.remove() won't hurt anything and should close any lingering preparedstatements as intended. the key, i think, is to set 'statement' to null just once, during initialization, and avoid setting 'statement' to null anywhere else (just rely on reassigning 'statement' to each new preparedstatement). Thank you again for everything.
[ July 28, 2008: Message edited by: Tom Griffith ]
 
Joanne Neal
Rancher
Posts: 3742
16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I assume you meant the close method rather than the remove method.
According to the Javadoc
Calling the method close on a Statement object that is already closed has no effect.
so it should be fine to call it more than once and probably okay to call it even if nothing needs to be released, although we probably need someone who knows more about JDBC than I do to confirm that.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Tom Griffith:
i think i'm just going to reuse the 'statement' variable and only set it to null at the very beginning during initialization..then call remove() on 'statement' after each sql op and in the finally. This way the old objects 'statement' pointed to should be garbage collected and the statement.remove() won't hurt anything and should close any lingering preparedstatements as intended. the key, i think, is to set 'statement' to null just once, during initialization, and avoid setting 'statement' to null anywhere else (just rely on reassigning 'statement' to each new preparedstatement). Thank you again for everything.

[ July 28, 2008: Message edited by: Tom Griffith ]


A PreparedStatement doesn't have a remove() method that I know of... do you mean close()?

The best technique here is to declare the statement in as small a scope as possible and call close() as soon as it is done. Do the same for the ResultSet (if any), and for the Connection object.

Setting the reference to null when you are done with it has no affect in the code you provided. The Object will remain in the heap until the Garbage Collector decides to clean it up. Setting it to null won't change that, all it does is release the reference to the Object, which is released when the variable goes out of scope anyway.

It is MUCH more important to always call close() on the Statements, ResultSets, and Connections. Not doing the close() method can leave these resources open and used, and will prevent the GC from cleaning up properly. Not calling close() is where you get into problems. Setting to null is nothing more than a sign that you are done.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
i think i'm just going to reuse the 'statement' variable and only set it to null at the very beginning during initialization..then call remove() on 'statement' after each sql op and in the finally.


I don't know if this is a matter of personal preference or not, but I would rather treat each SQL Op as its own block of code rather than a chain sharing the same variables. Example:


Ideally I would like to see each SQL Op in its own method as well...
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!