Subject Re: Should (Could) FBStatements be held in WeakHashMap
Author Roman Rokytskyy
Mark,

> In FBConnection active statements are held in a HashSet.
>
> I was wondering if anyone had thought of changing this to a
> WeakHashMap?

Short answer would be - "no". Long answer will follow.

> It would mean that if one forgets to call the stmt.close() method
> that they would get picked up by a System.gc() call.

According to specs if somebody forgets to call stmt.close(), it will
be called automatically when connection is closed. There's nothing
about garbage collection.

> Not that one would admit to using such poor coding style as to
> forget to add the close() :-). But in case one did you would get
> a :
>
> Exception in thread "main" java.lang.RuntimeException: Unable to
> close BLOB input stream."
>
> or similar message, which is not very clear.

Well... this is a bug, and it should be fixed in driver and not
worked around by not closing the statements.

> From there it took a fair amount of fiddling, eventually arriving
> at the (old) Heap Analysis Tool,
>
> http://java.sun.com/people/billf/heap/
>
> (I had to hack the code to get it to load profiles from jdk1.4.1)
> but then when I realised I had well over 20,000 FBCallableStatment
> instances, which then pointed to the correct source of the error.

What about closing the connection?

> The only link holding them in memory was the above HashMap. The
> looking at the code, in FBConnection:
>
> // This set contains all allocated but not closed statements
> // It is used to close them before the connection is closed
>
> private java.util.HashSet activeStatements =
> new java.util.HashSet();
>
> So closing the connection would work, but it would be nice to have a
> safty net, particularly since the error message is not so clear,
> which leads me to wonder if a WeakHashMap could be used here
> instead.

No, otherwise it makes no sense to track statements at all. Each open
statement handle eats some resources on server (probably there's even
a limit on max. number of open statements). So, forgetting to call
stmt.close() is a bug in application, same as memory leaks.

To solve this issue at work I have created a dynamic proxy for
Connection and PreparedStatement that track statement creation and
closing and print list of not closed statements with their allocation
point on connection.commit(), connection.rollback() and
connection.close(). This works perfectly.

Best regards,
Roman Rokytskyy