【问题标题】:Java memory leak caused by MySQL librariesMySQL 库导致的 Java 内存泄漏
【发布时间】:2025-12-14 17:35:01
【问题描述】:

我有一个线程来执行和更新带有一些值的数据库。我注释掉了对数据所做的所有操作,只留下了您可以在下面看到的行。在使用您在下面看到的行运行程序时,我遇到了内存泄漏。

这就是它在 VisualVM 中的样子

Mysql类

    public ResultSet executeQuery(String Query) throws SQLException {
        statement = this.connection.createStatement();
        resultSet = statement.executeQuery(Query);
        return resultSet;

    }



    public void executeUpdate(String Query) throws SQLException {
        Statement tmpStatement = this.connection.createStatement();
        
        tmpStatement.executeUpdate(Query);
        tmpStatement.close();
        tmpStatement=null;
        
    }

线程文件

public void run() {
        ResultSet results;
        String query;
        int id;
        String IP;
        int port;
        String SearchTerm;
        int sleepTime;
        while (true) {
            try {

                query = "SELECT * FROM example WHERE a='0'";
                results = this.database.executeQuery(query);

                while (results.next()) {
                    
                    id = results.getInt("id");
                
                    query = "UPDATE example SET a='1' WHERE id='"
                            + id + "'";
                    SearchTerm=null;
                    this.database.executeUpdate(query);
                }
                results.close();
                results = null;
                
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

在研究网络后,许多其他人都出现了这个问题,

https://forum.hibernate.org/viewtopic.php?f=1&t=987128

Is bone cp or mysql.jdbc.JDBC4Connection known for leaking?

如果你用谷歌搜索“jdbc4resultset 内存泄漏”,还有更多

【问题讨论】:

  • 每个单独的线程如何获取它的Connection 对象?很有可能问题就在那里
  • 每次都创建一个新语句会产生很多开销。查看PreparedStatement 以减少开销(处理和网络)、提高性能并提高安全性(自动转义特定于数据库的关键字以防止 SQL 注入)。
  • 看起来您正在泄漏ResultSet 实例。您可以进行堆转储并查看它们被占用的位置。
  • 我很确定您在某处有问题...我每天都使用 mysql jdbc 4.0 驱动程序(实际上每天使用数千次,因为它在生产代码中)并且没有任何已知的泄漏是由它引起的。

标签: java mysql jdbc memory-leaks


【解决方案1】:

泄漏是你的,不是 MySQL 的。你没有结束声明。

你的方法设计很差。它应该关闭语句,并且应该返回在语句关闭后仍然存在的内容,例如CachedRowSet

否则它根本不应该存在。只有三行,而且不支持查询参数,所以用处不大。我会直接删除它。

您似乎还拥有statement 作为实例成员,这很少是正确的。它应该是方法的本地。目前你的代码甚至不是线程安全的。

您还应该在 finally 块中关闭 ResultSet 以确保它被关闭。同上Statement

【讨论】:

    【解决方案2】:

    确保您明确关闭数据库连接。

    【讨论】: