RE: Memory leak in 7.0.3 JDBC driver

Rainer Mager <rmager@vgkk.com>

From: "Rainer Mager" <rmager@vgkk.com>
To: <sullivan@Mathcom.COM>, <pgsql-bugs@postgresql.org>
Date: 2001-06-20T23:21:32Z
Lists: pgsql-bugs

Attachments

I posted yesterday regarding a memory leak I found in the JDBC driver in
7.1. I didn't check but it is quite likely it also existed in 7.0. The patch
I created hasn't been checked by anyone else yet so I don't know if it helps
for others or not. Feel free to try it.

--Rainer


> -----Original Message-----
> From: pgsql-bugs-owner@postgresql.org
> [mailto:pgsql-bugs-owner@postgresql.org]On Behalf Of Steve Sullivan
> Sent: Monday, June 18, 2001 2:59 AM
> To: pgsql-bugs@postgresql.org
> Subject: [BUGS] Memory leak in 7.0.3 JDBC driver
>
>
>
> Hi,
>
> I'm running Postgresql 7.0.3 on Redhat 7.1 on a Pentium.
> When I use Connection.getCatalog() and similar calls,
> the amount of free memory slowly decreases.  I get:
>
> after get catalog: 0:  totmem: 2031616 freemem: 1899480
> after get catalog: 100:  totmem: 2031616 freemem: 1854576
> after get catalog: 200:  totmem: 2031616 freemem: 1810008
> after get catalog: 300:  totmem: 2031616 freemem: 1765104
> after get catalog: 400:  totmem: 2031616 freemem: 1720200
> after get catalog: 500:  totmem: 2031616 freemem: 1675296
> after get catalog: 600:  totmem: 2031616 freemem: 1630808
> after get catalog: 700:  totmem: 2031616 freemem: 1585904
> after get catalog: 800:  totmem: 2031616 freemem: 1541000
> after get catalog: 900:  totmem: 2031616 freemem: 1496096
>
> It's losing about 448 bytes per iteration.
> The Java test program I wrote is appended.  I invoked it using:
>
> java Tbtestc org.postgresql.Driver jdbc:postgresql:mydb myuser
> mypswd testtablea > loga
>
> If you need any further info, please contact me.
> Thanks,
>
> Steve
>
> ========================================
> Steve Sullivan    sullivan@mathcom.com
>
>    Mathcom Solutions, Inc.
>     * Java, XML, and web oriented development.
>     * Language development and translation.
>     * Optimization, simulation, and mathematical modeling.
>
> http://www.mathcom.com    303-494-7115
> ========================================
>
>
>
> ========== begin Tbtestc.java ==========
>
> import java.io.PrintWriter;
> import java.sql.Connection;
> import java.sql.DatabaseMetaData;
> import java.sql.DriverManager;
> import java.sql.PreparedStatement;
> import java.sql.ResultSet;
> import java.sql.ResultSetMetaData;
> import java.sql.SQLException;
> import java.sql.Statement;
> import java.sql.Types;
>
> /**
>  * Tests simple jdbc access for memory leaks.
>  */
>
>
> public class Tbtestc {
> 	public static void main( String[] args) {
> 		new Tbtestc( args);
> 	}
>
> 	void prtln( String msg) {
> 		System.out.println( msg);
> 	}
>
> 	void badparms( String msg)
> 	{
> 		prtln("");
> 		prtln("Testc: Error: " + msg);
> 		prtln("args:  drivername url userid pswd tabname
> (will be deleted)");
> 		System.exit(1);
> 	}
>
>
> 	public Tbtestc( String[] args) {
> 		int ii;
>
> 		if (args.length != 5) badparms("wrong num parms");
> 		String drivername	= args[0];
> 		String url			= args[1];
> 		String userid		= args[2];
> 		String pswd			= args[3];
> 		String tabname		= args[4];
>
> 	    // Connect to database and run the tests
> 		try {
> 			testit( drivername, url, userid, pswd, tabname);
> 		}
> 		catch( Exception exc) {
> 			prtln("Tbtestc: error: " + exc);
> 			exc.printStackTrace();
> 		}
> 	}
>
>
> 	void testit(
> 		String drivername,
> 		String url,
> 		String userid,
> 		String pswd,
> 		String tabname)
> 	throws SQLException, ClassNotFoundException
> 	{
> 		int iterlim = 1000;
> 		int iterdelta = 100;
> 		int ii, jj, kk;
> 		int ncols;
> 		String tstg;
> 		ResultSet rs = null;
> 		int maxcolwidth = 30;
>
> 	    Connection dbcon = null;
> 		Statement dbst = null;
>
> 	    // Load the driver
> 		Class.forName( drivername);
>
>     	prtln("Connecting to Database URL = " + url);
> 		dbcon = DriverManager.getConnection( url, userid, pswd);
> 		prtln("got dbcon.");
> 		dbst = dbcon.createStatement();
> 		prtln("got dbst.");
>
> 		try { dbst.executeUpdate("drop table " + tabname); }
> 		catch( SQLException sqe) {
> 			prtln("could not drop table " + tabname +
> ": " + sqe);
> 		}
>
> 		dbst.executeUpdate("create table " + tabname
> 			+ " (colstg varchar(22) not null,"
> 			+ " colint integer not null,"
> 			+ " primary key (colstg, colint))");
> 		prtln("testit: created " + tabname);
>
> 		prtfreemem("before get catalog");
> 		String catalog = null;
> 		int isol = 0;
> 		boolean readonly = false;
> 		boolean autocommit = false;
> 		for (kk = 0; kk < iterlim; kk++) {
> 			catalog = dbcon.getCatalog();
> 			isol = dbcon.getTransactionIsolation();
> 			readonly = dbcon.isReadOnly();
> 			autocommit = dbcon.getAutoCommit();
> 			if (kk % iterdelta == 0) prtfreemem("after
> get catalog: " + kk);
> 		}
> 		prtfreemem("after get catalog");
> 		prtln("    catalog: " + catalog);
> 		prtln("    transaction isolation level: " + isol);
> 		prtln("    read only: " + readonly);
> 		prtln("    auto commit: " + autocommit);
>
> 		DatabaseMetaData dbm = null;
> 		for (kk = 0; kk < iterlim; kk++) {
> 			dbm = dbcon.getMetaData();
> 			if (kk % iterdelta == 0) prtfreemem("after
> get dbm: " + kk);
> 		}
> 		prtfreemem("after get dbm");
> 		String prodname = null;
> 		String version = null;
> 		String geturl = null;
> 		String getuser = null;
> 		for (kk = 0; kk < iterlim; kk++) {
> 			prodname = dbm.getDatabaseProductName();
> 			version = dbm.getDatabaseProductVersion();
> 			geturl = dbm.getURL();
> 			getuser = dbm.getUserName();
> 			if (kk % iterdelta == 0) prtfreemem("after
> get prodname: " + kk);
> 		}
> 		prtfreemem("after get prodname");
> 		prtln("database meta data:");
> 		prtln("    product name: " + prodname);
> 		prtln("    version: " + version);
> 		prtln("    URL: " + geturl);
> 		prtln("    user: " + getuser);
>
> 		for (kk = 0; kk < iterlim; kk++) {
> 			ResultSet keyrs = dbm.getPrimaryKeys(
> 				null, null,			//
> catalog, schema
> 				tabname);
> 			keyrs.close();
> 			if (kk % iterdelta == 0) prtfreemem("after
> get keys: " + kk);
> 		}
> 		prtfreemem("after get keys");
>
> 	}
>
>
>
> 	void prtfreemem( String msgparm) {
> 		Runtime runtime = Runtime.getRuntime();
> 		runtime.gc();
> 		long totmem = runtime.totalMemory();
> 		long freemem = runtime.freeMemory();
> 		String msg = msgparm + ": "
> 			+ " totmem: " + totmem
> 			+ " freemem: " + freemem;
> 		System.out.println( msg);
> 	}
>
>
> } // end class Tbtestc
>
>
> ========== end Tbtestc.java ==========
>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster