简体   繁体   中英

Memory Leak application using JDBC

I'm using mysql-connector-java-5.1.21 and I am getting a memory leak for which Memory Analyzer suspects java.lang.Class and among the biggest instances mysql.jdbc shows up. I have gone through the code and made sure all connections, results and statements are properly closed by I am still getting a leak.

1,529 instances of "java.lang.Class", loaded by "<system class loader>" occupy 711,632 (41.68%) bytes. 

Biggest instances:
•class com.mysql.jdbc.NonRegisteringDriver @ 0x381323f8 - 97,400 (5.70%) bytes. 
•class java.io.ObjectStreamClass$Caches @ 0x3d070568 - 91,872 (5.38%) bytes. 
•class java.lang.System @ 0x3d03da20 - 67,224 (3.94%) bytes. 
•class com.mysql.jdbc.SingleByteCharsetConverter @ 0x382a7438 - 66,032 (3.87%) bytes. 
•class java.lang.ref.Finalizer @ 0x3d03e260 - 65,888 (3.86%) bytes. 
•class com.sun.org.apache.xerces.internal.util.XMLChar @ 0x380bc528 - 65,592 (3.84%) bytes. 
•class com.mysql.jdbc.ConnectionPropertiesImpl @ 0x381ab5f8 - 32,456 (1.90%) bytes. 

The code is running in a loop with a delay. Currently the code opens a connection each interval. Should I just open one connection and pass it to my method? Either way I am not sure why that would be causing the leak. Any help is appreciated.

Here's some of the code, it should give you a good idea of how I am using jdbc and mysql.

    try {


        url+=database+"?zeroDateTimeBehavior=convertToNull"; 
        // LatestTime in SQL table defaults 0000-00-00 00:00:00 which java can't handle. zeroDateTimeBehaviour=convertToNull cause JDBC to null for a zero date.

        Class.forName("com.mysql.jdbc.Driver").newInstance();
        conn = DriverManager.getConnection(url,user,password);
        System.out.println(CurrentTime()+": "+"Connected to "+database);
    }
    catch (Exception e)     
    {

            System.err.println(CurrentTime()+": "+e.getMessage());
            System.err.println(CurrentTime()+": "+"Unable to Connect");
    }
    finally
    {
        if (conn!=null)
        {
            try {
                // Create Statements for SQL queries
                Statement query= conn.createStatement();

                // Get all records from phonelog which have yet to be processed
                query.executeQuery("SELECT * from phonelog where Recordnum>"+Recordnum);
                ResultSet rs = query.getResultSet();

                // Process each row from query result
                while (rs.next()) {
                }
                JDBCHelper.close(rs);

                String plupdate="update Counters set value='"+Recordnum+"' where name='plposition'";
                submit.executeUpdate(plupdate);
                JDBCHelper.close(query);
            }
            catch (SQLException SQLe) {
                System.err.println(CurrentTime()+": "+SQLe.getMessage());
            }

                JDBCHelper.close(conn);

                System.out.println (CurrentTime()+": "+"Disconnected");
        }
    }

Java will create objects and up memory until its near the -Xmx max heap size setting, then it will run a garbage collection to free up space. You should startup with a -Xmx setting to control how much memory the JVM can use. You should also be aware that the Connector/J JDBC driver buffers the entire result in memory by default.

If I perform a garbage collection with jconsole the heap memory usage drops back down

Then it does not seem a leak; perhaps you can start your JVM using a the -Xmx flag to limit the max. amount of memory allocated to the JVM. This might trigger more often GC.

Or perhaps perform a full GC in your loop: System.gc() -- usually not recommended at all but in case of your small application might do the trick.

While it was true that some of what I was seeing was freed resources waiting for the garbage collection, it turns out that it was mostly JDBC connections. Repeatly opening and closing connections was creating a memory leak. I switched the code so that it only uses one connection and jconsole is showing no signs of a memory leak now. Credit should be given to user1443778 for suggesting that I just needed one connection. The PreparedStatments suggestion was also good as I rewrote the code to use them.

Thank you also for the suggestion to use a ConnectionPool. It's a good suggestion but I probably won't bother with that until we move to VPS with Tomcat or JBOSS.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM