PreparedStatement.java.diff
application/octet-stream
Filename: PreparedStatement.java.diff
Type: application/octet-stream
Part: 0
Message:
RE: Memory leak in 7.0.3 JDBC driver
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| PreparedStatement.java.new | 28 | 18 |
--- PreparedStatement.java Sat Feb 17 01:45:00 2001
+++ PreparedStatement.java.new Wed Jun 20 12:34:57 2001
@@ -39,10 +39,12 @@
// Some performance caches
private StringBuffer sbuf = new StringBuffer();
- // We use ThreadLocal for SimpleDateFormat's because they are not that
- // thread safe, so each calling thread has its own object.
- private ThreadLocal tl_df = new ThreadLocal(); // setDate() SimpleDateFormat
- private ThreadLocal tl_tsdf = new ThreadLocal(); // setTimestamp() SimpleDateFormat
+ // Because SimpleDateFormat is not thread safe we create one for each
+ // PreparedStatemnt here AND synchronize on it for each usage.
+ // We can NOT use ThreadLocal because they are not freed until the thread
+ // completes. This would be a memory leak for long running threads.
+ private SimpleDateFormat df = null;
+ private SimpleDateFormat tsdf = null;
/**
* Constructor for the PreparedStatement class.
@@ -90,9 +92,6 @@
* New in 7.1 - overides Statement.close() to dispose of a few local objects
*/
public void close() throws SQLException {
- // free the ThreadLocal caches
- tl_df.set(null);
-
super.close();
}
@@ -332,14 +331,18 @@
*/
public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
{
- SimpleDateFormat df = (SimpleDateFormat) tl_df.get();
- if(df==null) {
+ // The df DateFormat is initialized here to delay creation until needed.
+ if( df == null ) {
+ synchronized( this ) {
+ if( df == null ) {
df = new SimpleDateFormat("''yyyy-MM-dd''");
- tl_df.set(df);
+ }
+ }
}
- set(parameterIndex, df.format(x));
-
+ // We must synchronize here because SimpleDateFormat is not thread safe.
+ synchronized( df ) {
+ set( parameterIndex, df.format(x) );
// The above is how the date should be handled.
//
// However, in JDK's prior to 1.1.6 (confirmed with the
@@ -351,6 +354,7 @@
//
//set(parameterIndex, df.format(new java.util.Date(x.getTime()+86400000)));
}
+ }
/**
* Set a parameter to a java.sql.Time value. The driver converts
@@ -375,17 +379,22 @@
*/
public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
{
- SimpleDateFormat df = (SimpleDateFormat) tl_tsdf.get();
- if(df==null) {
- df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- tl_tsdf.set(df);
+ // The tsdf DateFormat is initialized here to delay creation until needed.
+ if( tsdf == null ) {
+ synchronized( this ) {
+ if( tsdf == null ) {
+ tsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ tsdf.setTimeZone(TimeZone.getTimeZone("GMT"));
+ }
+ }
}
- df.setTimeZone(TimeZone.getTimeZone("GMT"));
+ // We must synchronize here because SimpleDateFormat is not thread safe.
+ synchronized( tsdf ) {
// Use the shared StringBuffer
synchronized(sbuf) {
sbuf.setLength(0);
- sbuf.append("'").append(df.format(x)).append('.').append(x.getNanos()/10000000).append("+00'");
+ sbuf.append("'").append(tsdf.format(x)).append('.').append(x.getNanos()/10000000).append("+00'");
set(parameterIndex, sbuf.toString());
}
@@ -393,6 +402,7 @@
// to be identical. Pays to read the docs ;-)
//set(parameterIndex,"'"+x.toString()+"'");
}
+ }
/**
* When a very large ASCII value is input to a LONGVARCHAR parameter,