Обсуждение: Memory leak ?

Поиск
Список
Период
Сортировка

Memory leak ?

От
Pierre Le Mouëllic
Дата:
<font face="Xerox Sans">With this code :<br /></font> <pre>public class TestJDBC {
   private static Timer timer;
   private static Connection connDB;   private static PreparedStatement sQLStatement;
   public static void main(String[] args) throws SQLException, ClassNotFoundException {
       connexion("jdbc:postgresql://praslin.qual.dc1:5432/G01DPM", "postgres8", "password");              timer = new
Timer();      timer.schedule(new local_task(), 1000L, 1000);       }
 
   static class local_task extends TimerTask {
       public void run() {           ResultSet rs=null;           try {               sQLStatement.setInt(1, 2602);
         rs = sQLStatement.executeQuery();               sQLStatement.setInt(1, 2604);               rs =
sQLStatement.executeQuery();              sQLStatement.setInt(1, 2605);               rs = sQLStatement.executeQuery();
         } catch (SQLException e) {           }           finally{
 
               try {                   if(rs!=null)                       rs.close();               } catch
(SQLExceptione) {               }               rollBack();           }       }   }
 
   public static void connexion(String chemin, String user, String password) throws SQLException,
ClassNotFoundException  {       Class.forName("org.postgresql.Driver");       String url =
chemin+"?user="+user+"&password="+password;
       //    Connexion       connDB = DriverManager.getConnection(url);       connDB.setAutoCommit(false);
initPreparedStatement();  }
 
   private static void initPreparedStatement() throws SQLException   {       sQLStatement =
connDB.prepareStatement("selectf_transite(?,'FPL','225',9,'test','','')");   }
 
   public static void rollBack()   {       try       {           connDB.rollback();       }       catch(SQLException
ex)      {       }   }
 
}</pre> In eclipse Helios profiler, Jdbc3ResultSet live instances increase (and never decrease). Same thing with
org.postgresql.core.v3.QueryExecutorImpl$ErrorTrackingResultHandlerand org.postgresql.core.v3.QueryExecutorImpl$1
classes.<br/><br /> f_transite stored procedure make some select, insert and update. If you need more explanation, i
cangive it to you.<br /><br /> Java 6<br /> postgresql-9.0-801.jdbc3.jar<br /> PostgreSQL 8.2.5 on
powerpc-apple-darwin8.8.0,compiled by GCC powerpc-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build
5363)<br/><br /> Is it a memory leak ? Or my java code is wrong ?<br /><br /><div class="moz-signature"><font
color="#000080"face="Arial" size="2"><b>Pierre LE MOUËLLIC<br /></b></font><font color="#000080" face="Arial"
size="1"><br/></font> <a href="mailto:pierre.lemouellic@xgs-france.com" moz-do-not-send="true"><font color="blue"
size="1"><u>pierre.lemouellic@xgs-france.com</u></font></a><br/></div> 

Re: Memory leak ?

От
Oliver Jowett
Дата:
2011/4/6 Pierre Le Mouëllic <pierre.lemouellic@xgs-france.com>:

> In eclipse Helios profiler, Jdbc3ResultSet live instances increase (and
> never decrease). Same thing with
> org.postgresql.core.v3.QueryExecutorImpl$ErrorTrackingResultHandler and
> org.postgresql.core.v3.QueryExecutorImpl$1 classes.

When profiling, has a full GC & weak reference collection happened
before you count "live instance"?
Probably those "live" instances are only weakly reachable and will be
cleaned up later.
(The driver uses weak references + a reference queue that is polled
before each query execution to clean up server-side allocated
resources corresponding to JDBC statements / resultsets that were not
properly closed, just discarded)

If that's not the problem, I'd need to know the path from a GC root to
the live instances.

Oliver

Re: Memory leak ?

От
Guillaume Cottenceau
Дата:
Pierre Le Mouëllic <pierre.lemouellic 'at' xgs-france.com> writes:

> With this code :
>
> public class TestJDBC {

[...]

>             try {
>                 sQLStatement.setInt(1, 2602);
>                 rs = sQLStatement.executeQuery();
>                 sQLStatement.setInt(1, 2604);
>                 rs = sQLStatement.executeQuery();
>                 sQLStatement.setInt(1, 2605);
>                 rs = sQLStatement.executeQuery();
>             } catch (SQLException e) {
>             }
>             finally{
>
>                 try {
>                     if(rs!=null)
>                         rs.close();

e.g. you explicitely close only the last resultset of the three
you produced (assuming no exception)

> In eclipse Helios profiler, Jdbc3ResultSet live instances increase (and never
> decrease). Same thing with

Garbage collection is not predictable, closing resultsets (and
statements) is strongly adviced if you want to release JDBC
resources in a timely manner.

I have never used this profiler but it would be interesting to
know if any references are keeping these objects alive (then we
could begin thinking of a leak), or if they are only not yet
collected by the GC because it decided not to do it yet for any
reason.

Interestingly, the diff between:

http://download.oracle.com/javase/1.4.2/docs/api/java/sql/Statement.html#close()

and:

http://download.oracle.com/javase/6/docs/api/java/sql/Statement.html#close()

shows they've removed "Statement object is automatically closed
when it is garbage collected." no idea why though. probably a
more seasoned PG-JDBC dev/user would have?

--
Guillaume Cottenceau

Re: Memory leak ?

От
Lew
Дата:
Guillaume Cottenceau wrote:
> Pierre Le Mouëllic writes:
>
>> With this code :
>>
>> public class TestJDBC {
>
> [...]
>
>>              try {
>>                  sQLStatement.setInt(1, 2602);
>>                  rs = sQLStatement.executeQuery();
>>                  sQLStatement.setInt(1, 2604);
>>                  rs = sQLStatement.executeQuery();
>>                  sQLStatement.setInt(1, 2605);
>>                  rs = sQLStatement.executeQuery();
>>              } catch (SQLException e) {
>>              }
>>              finally{
>>
>>                  try {
>>                      if(rs!=null)
>>                          rs.close();
>
> e.g. you explicitely close only the last resultset of the three
> you produced (assuming no exception)

So?  Why is that an issue?

<http://download.oracle.com/javase/6/docs/api/java/sql/ResultSet.html>

"A ResultSet object is automatically closed when the Statement object that
generated it is closed, re-executed, or used to retrieve the next result from
a sequence of multiple results."

>> In eclipse Helios profiler, Jdbc3ResultSet live instances increase (and never
>> decrease). Same thing with
>
> Garbage collection is not predictable, closing resultsets [sic] (and
> statements) is strongly adviced if you want to release JDBC
> resources in a timely manner.

No.

Closing a 'ResultSet' is actually not advised.  Well, sometimes, but generally
you should close its 'Statement'.  In the OP's case he did the right thing by
closing just the last 'ResultSet', since he wanted his 'Statement' to stay alive.

>
> I have never used this profiler but it would be interesting to
> know if any references are keeping these objects alive (then we
> could begin thinking of a leak), or if they are only not yet
> collected by the GC because it decided not to do it yet for any
> reason.

I tend not to conflate the issues of memory resources and external resources
like database connections.

> Interestingly, the diff between:
>
> http://download.oracle.com/javase/1.4.2/docs/api/java/sql/Statement.html#close()
>
> and:
>
> http://download.oracle.com/javase/6/docs/api/java/sql/Statement.html#close()
>
> shows they've removed "Statement object is automatically closed
> when it is garbage collected." no idea why though. probably a
> more seasoned PG-JDBC dev/user would have?

One should never have depended exclusively on the GC to close resources in any
event.

--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedia/commons/c/cf/Friz.jpg

Re: Memory leak ?

От
Guillaume Cottenceau
Дата:
Lew <noone 'at' lewscanon.com> writes:

> Guillaume Cottenceau wrote:
>> Pierre Le Mouëllic writes:
>>
>>> With this code :
>>>
>>> public class TestJDBC {
>>
>> [...]
>>
>>>              try {
>>>                  sQLStatement.setInt(1, 2602);
>>>                  rs = sQLStatement.executeQuery();
>>>                  sQLStatement.setInt(1, 2604);
>>>                  rs = sQLStatement.executeQuery();
>>>                  sQLStatement.setInt(1, 2605);
>>>                  rs = sQLStatement.executeQuery();
>>>              } catch (SQLException e) {
>>>              }
>>>              finally{
>>>
>>>                  try {
>>>                      if(rs!=null)
>>>                          rs.close();
>>
>> e.g. you explicitely close only the last resultset of the three
>> you produced (assuming no exception)
>
> So?  Why is that an issue?

Did I say it is an issue?

> <http://download.oracle.com/javase/6/docs/api/java/sql/ResultSet.html>
>
> "A ResultSet object is automatically closed when the Statement object
> that generated it is closed, re-executed, or used to retrieve the next
> result from a sequence of multiple results."

Yes, it is not an issue.

>>> In eclipse Helios profiler, Jdbc3ResultSet live instances increase (and never
>>> decrease). Same thing with
>>
>> Garbage collection is not predictable, closing resultsets [sic] (and
>> statements) is strongly adviced if you want to release JDBC
>> resources in a timely manner.
>
> No.
>
> Closing a 'ResultSet' is actually not advised.  Well, sometimes, but
> generally you should close its 'Statement'.

I'm no expert on that, so it's one more reason why I'm not going
to lose too much time on that by answering once to illustrate my
claims, and then let it go if that creates more fuss. I hope I
can learn from this actually so that's not a call from you to not
answer that message if you see wrong claims.

I'm stating closing (of resultsets and statements) is adviced
from memories of messages on this list and other lists, and this
seems to be supported by the documentation over there:

http://download.oracle.com/javase/6/docs/api/java/sql/ResultSet.html#close()

In particular:

"Releases this ResultSet object's database and JDBC resources
immediately instead of waiting for this to happen when it is
automatically closed."

I don't see why it would be "actually not adviced" as you say. So
there is an API, whose name is "close" which is similar to other
names used in java API to immediately release external resources
instead of waiting for the GC to do so, and whose documentation
says the same thing, but it would be adviced to not use it? Seems
odd.

> In the OP's case he did the right thing by closing just the
> last 'ResultSet', since he wanted his 'Statement' to stay
> alive.

Closing the two first resultsets would not allow this statement
to stay alive? That doesn't seem supported by the documentation
of the close method.

--
Guillaume Cottenceau