java - 简单的 mysql/jdbc 代码导致内存泄漏?

标签 java jdbc heap-dump

我第一次尝试分析堆转储以查找内存泄漏。我正在使用 MAT 打开堆转储,立刻就很清楚它是一个对象?它几乎占据了整个堆,它是一个 sql 类 com.mysql.cj.jdbc.ConnectionImpl。

由于 sql 实际上只在我的代码的一部分中使用,所以它基本上必须是这里的一小段代码......

static Connection getDBconn() {
    Connection conn = null;
    while (conn == null) {
        try {
            conn = DriverManager.getConnection(serverURL, user, pass);
        } catch (SQLException e) {
            Logger.logError(e);
        }
    }
    return conn;
}
static void update(String sql) {
    while (currConn == null)
        currConn = getDBconn();
    boolean error = false;
    do {
        try {
            currConn.createStatement().executeUpdate(sql);
        } catch (SQLException e) {
            try {
                currConn.close();
            } catch (SQLException e1) {
                Logger.logError(e1);
            }
            currConn = getDBconn();
            Logger.logError(e);
            error = true;
        }
    } while (error);
}
static ResultSet query(String sql) {
    while (currConn == null)
        currConn = getDBconn();
    ResultSet rs = null;
    while (rs == null) {
        try {
            rs = currConn.createStatement().executeQuery(sql);
        } catch (SQLException e) {
            try {
                currConn.close();
            } catch (SQLException e1) {
                Logger.logError(e1);
            }
            currConn = getDBconn();
            Logger.logError(e);
        }
    }
    return rs;
}

这段代码的作用基本上是将查询/更新语句包装在一些方法中,以确保每个命令最终总是被执行,即使出现错误也是如此。我的程序将运行很长时间并发出许多请求,我想确保它自动处理所有可能的问题而不中断程序。

我写的内容将工作大约一个小时左右,然后即使我将堆设置为 8GB,这显然是多余的,我也会收到内存不足错误。我还应该注意到我没有收到任何 sql 错误,因此它甚至没有进入 catch block 。显然,这段代码存在某种泄漏,但我无法弄清楚它可能是什么。如有任何建议,我们将不胜感激,如果需要,我可以提供有关堆转储的更多信息。

最佳答案

当您不需要两次连接时,您就会获得连接

 try {
            currConn.close();
        } catch (SQLException e1) {
            Logger.logError(e1);
        }
 -->   currConn = getDBconn();
        Logger.logError(e);

只需在 currConn.close(); 之后删除 currConn = getDBconn() 就不会出现连接泄漏。

更好的是,即使没有发生错误,最后也关闭连接:

    try {
        rs = currConn.createStatement().executeQuery(sql);
    } catch (SQLException e) {
        Logger.logError(e);
    finally{
        try {
            currConn.close();
        } catch (SQLException e1) {
             Logger.logError(e1);
        }
    }

还创建一个方法来防止代码重复和关闭连接的不同实现。

关于java - 简单的 mysql/jdbc 代码导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48201545/

相关文章:

java - 当 ResultSet 没有执行时?

适用于 Windows VHD API 的 Java 库

java - 如果连接被数据库关闭,我是否需要手动关闭它?

sql-server - PySpark 中通过 JDBC 的 SQL Server

用于检查给定用户、架构、表是否存在的 Java 代码?

java - 在 Java 中使用 Freebase API

java - JDK 源码 : code repetition Collection. java 和 Set.java

java - HeapDump 或单独的映射文件中的 JVMTI 标记

java - 如何从二进制堆转储中提取jvm参数

java - 堆转储中有很多 hibernate 查询。我该如何限制?