Re: JDBC PreparedStatement Memory Leak. - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: JDBC PreparedStatement Memory Leak.
Date
Msg-id 200204141724.g3EHOfI13886@candle.pha.pa.us
Whole thread Raw
In response to Re: JDBC PreparedStatement Memory Leak.  (Barry Lind <barry@xythos.com>)
List pgsql-patches
Leif, can you respond to this?


---------------------------------------------------------------------------

Barry Lind wrote:
> Leif,
>
> In looking at this patch, I don't understand the bug that it is trying
> to fix.  I looked over how the ThreadLocal objects are being used in the
> code and don't see how they could cause a memory leak.  Can you explain
> where the bug exists in the current logic?  Or alternatively can you
> provide a test case that demonstrates the problem so that I can look
> into it some more here.
>
> Also when submitting patches, please send them in diff -c format.
>
> thanks,
> --Barry
>
>
> Bruce Momjian wrote:
> > Can you send a context diff, diff -c?  Thanks.
> >
> > ---------------------------------------------------------------------------
> >
> > Leif Mortenson wrote:
> >
> >>I encountered a very large memory leak when using PreparedStatements in
> >>a Java Application.
> >>
> >>The memory leak only shows itself where all of the following are true:
> >>1) The Threads which use the PreparedStatements have a long lifetime.
> >>2) setDate() or setTimestamp is called on the PreparedStatements.
> >>3) The PreparedStatements are being used enough to notice the leak.
> >>
> >>In my application, my JVM was running out of memory around 330MB after
> >>about 1 hour of
> >>continuous opertion. I was able to find the problem by using the Java
> >>Profiler. It showed
> >>that around 100,000 instances of SimpleDateFormat and their subobjects
> >>were hanging around
> >>in memory.
> >>
> >>It turns out that this was being caused by the way PreparedStatement was
> >>using
> >>ThreadLocal instances. Each one was creating a SimpleDateFormat which
> >>via the
> >>ThreadLocal gets set into a HashMap in the current Thread. These never
> >>get cleaned
> >>up until the Thread itself is GCed.
> >>
> >>It looks like this had been discovered last summer and there were some
> >>posts about a
> >>patch having been committed. But the problem is still there.
> >>
> >>Here is the patch that I made to fix this.
> >>
> >>Cheers,
> >>Leif
> >>
> >>RCS file:
> >>/projects/cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java,v
> >>retrieving revision 1.24
> >>diff -w -r1.24 PreparedStatement.java
> >>42,45c42,45
> >>< // We use ThreadLocal for SimpleDateFormat's because they are not that
> >>< // thread safe, so each calling thread has its own object.
> >>< private static ThreadLocal tl_df = new ThreadLocal(); // setDate()
> >>SimpleDateFormat
> >>< private static ThreadLocal tl_tsdf = new ThreadLocal(); //
> >>setTimestamp() SimpleDateFormat
> >>---
> >>
> >>>// Store a copy of SimpleDataFormats for each instance and synchronize
> >>
> >>them as they
> >>
> >>>// are not very thread safe.
> >>>private static SimpleDateFormat df; // setDate() SimpleDateFormat
> >>>private static SimpleDateFormat tsdf; // setTimestamp() SimpleDateFormat
> >>
> >>351c351
> >>< SimpleDateFormat df = (SimpleDateFormat) tl_df.get();
> >>---
> >>
> >>>SimpleDateFormat df = this.df;
> >>
> >>354,355c354,356
> >>< df = new SimpleDateFormat("''yyyy-MM-dd''");
> >>< tl_df.set(df);
> >>---
> >>
> >>>// It is possible that two threads could get in here, but it
> >>>// does not cause problems.
> >>>this.df = df = new SimpleDateFormat("''yyyy-MM-dd''");
> >>
> >>357c358,365
> >>< set(parameterIndex, df.format(x));
> >>---
> >>
> >>>String formatX;
> >>>synchronized(df)
> >>>{
> >>>// SimpleDateFormats are not thread safe.
> >>>formatX = df.format(x);
> >>>}
> >>>set(parameterIndex, formatX);
> >>
> >>407c415
> >>< SimpleDateFormat df = (SimpleDateFormat) tl_tsdf.get();
> >>---
> >>
> >>>SimpleDateFormat df = tsdf;
> >>
> >>409a418,419
> >>
> >>>// It is possible that two threads could get in here, but it
> >>>// does not cause problems.
> >>
> >>412c422
> >>< tl_tsdf.set(df);
> >>---
> >>
> >>>tsdf = df;
> >>
> >>424a435,441
> >>
> >>>String formatX;
> >>>synchronized(df)
> >>>{
> >>>// SimpleDateFormats are not thread safe.
> >>>formatX = df.format(x);
> >>>}
> >>>
> >>
> >>429c446
> >><
> >>sbuf.append("'").append(df.format(x)).append('.').append(decimal).append("+00'");
> >>---
> >>
> >>sbuf.append("'").append(formatX).append('.').append(decimal).append("+00'");
> >>
> >>
> >>
> >>
> >>---------------------------(end of broadcast)---------------------------
> >>TIP 5: Have you checked our extensive FAQ?
> >>
> >>http://www.postgresql.org/users-lounge/docs/faq.html
> >>
> >
> >
>
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/users-lounge/docs/faq.html
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

pgsql-patches by date:

Previous
From: "Christopher Kings-Lynne"
Date:
Subject: BETWEEN Help
Next
From: Tom Lane
Date:
Subject: Re: BETWEEN Help