【问题标题】:Memory Leak application using JDBC使用 JDBC 的内存泄漏应用程序
【发布时间】:2012-08-27 18:43:13
【问题描述】:

我正在使用 mysql-connector-java-5.1.21,我遇到了内存泄漏,Memory Analyzer 怀疑是 java.lang.Class 和最大的实例之一 mysql。 jdbc 出现。我已经检查了代码并确保所有连接、结果和语句都已正确关闭,但仍然存在泄漏。

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. 

代码在一个有延迟的循环中运行。目前,代码在每个间隔打开一个连接。我应该只打开一个连接并将其传递给我的方法吗?无论哪种方式,我都不确定为什么会导致泄漏。任何帮助表示赞赏。

这里有一些代码,它应该能让你很好地了解我是如何使用 jdbc 和 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");
        }
    }

【问题讨论】:

  • 如果我使用 jconsole 执行垃圾回收,堆内存使用率会下降。
  • 考虑发布您的代码,这将有助于分析您的问题。
  • 内存小于 1mb。为什么会出现问题?
  • 我们有非常严格的内存限制,因为这是在共享的 Web 主机上运行的。堆内存在 50 分钟内从峰值 6mb 增加到超过 7mb 并继续增加。我们需要同时运行这个应用程序的 2 个版本,我相信我们的内存量不是很大(不到半个 gig)。最终我们将迁移到 VPS,但我这样做是为了在我们的演示过程中没有托管公司终止进程的情况下运行。
  • 使用准备好的语句,我认为它不会解决您的问题,但无论如何它都是一件好事。此外,我在 GUI 应用程序中有一些 jdbc 代码在应用程序终止之前一直保持连接,即当用户按下按钮但它只打开一个连接时,它会发出准备好的语句 jdbc 请求。

标签: java mysql jdbc memory-leaks


【解决方案1】:

Java 将创建对象并增加内存,直到其接近 -Xmx 最大堆大小设置,然后它将运行垃圾收集以释放空间。您应该使用 -Xmx 设置启动以控制 JVM 可以使用多少内存。您还应该知道,Connector/J JDBC 驱动程序默认将整个结果缓冲在内存中。

【讨论】:

  • 你会建议我对查询设置限制吗?当我转移到 VPS 时,我不确定这是否会成为问题,但有可能会同时发布多达 10,000 多个交易,并且此流程服务器目前将请求所有 10K 以及任何新的其他来源的交易。或者有没有 Connector/J JDBC 的替代品?
  • 是的,我肯定会限制您的查询。如果批量较大,可能需要几轮才能完成,但这比您的应用程序内存不足要好得多。
【解决方案2】:

如果我使用 jconsole 执行垃圾回收,堆内存使用率会下降

那么它似乎没有泄漏;也许您可以使用 -Xmx 标志来限制最大值来启动 JVM。分配给 JVM 的内存量。这可能会更频繁地触发 GC。

或者也许在你的循环中执行一次完整的 GC:System.gc()——通常根本不推荐,但如果你的小应用程序可能会做到这一点。

【讨论】:

    【解决方案3】:

    虽然我确实看到了一些等待垃圾回收的释放资源,但事实证明它主要是 JDBC 连接。反复打开和关闭连接会造成内存泄漏。我切换了代码,使其仅使用一个连接,并且 jconsole 现在没有显示内存泄漏的迹象。应该感谢 user1443778 建议我只需要一个连接。 PreparedStatments 建议也很好,因为我重写了代码以使用它们。

    也感谢您提出使用 ConnectionPool 的建议。这是一个很好的建议,但在我们使用 Tomcat 或 JBOSS 迁移到 VPS 之前,我可能不会为此烦恼。

    【讨论】:

      猜你喜欢
      • 2016-03-28
      • 2010-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多