java - JdbcRowSet 中的内存泄漏

标签 java mysql jdbc memory-leaks rowset

我尝试使用大表(大约一万条记录)中的记录填充 JdbcRowSet。我尝试了两种变体(参见下面的代码):

  1. 创建连接对象,使用JdbcRowSetImpl(connection)实例化,循环执行查询。
  2. 使用 JdbcRowSetImpl(DriverManager.getConnection("jdbc:....") 实例化,循环执行查询。

第一个变体会导致内存泄漏,直到堆已满。第二种变体没有内存泄漏。有人可以解释一下为什么第一个在重用连接对象时会导致内存泄漏吗?

谢谢

1 的代码。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.sql.rowset.JdbcRowSet;
import com.sun.rowset.JdbcRowSetImpl;

public class JdbcRowSetMemoryLeak {

/**
 * @param args
 */
public static void main(String[] args) {
    String username = "user";
    String password = "password";
    Connection connection = null;
    try {
        Class.forName("com.mysql.jdbc.Driver");
        connection = DriverManager.getConnection("jdbc:mysql://localhost/db_ams?user=" + username + "&password=" + password);
    } catch (ClassNotFoundException | SQLException e) {
        e.printStackTrace();
    }
    JdbcRowSet jdbcRS = null;
    for (int i=0;i<150;i++){
        System.out.println(i);
        try {
            jdbcRS = new JdbcRowSetImpl(connection); // <-- Memory is leaking
            jdbcRS.setCommand("Select * from sample_t;");
            jdbcRS.execute();
//              jdbcRS.close(); <-- Returns a null pointer Exception
            jdbcRS = null;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

}

2 的代码。

import java.sql.DriverManager;
import java.sql.SQLException;
import javax.sql.rowset.JdbcRowSet;
import com.sun.rowset.JdbcRowSetImpl;

public class JdbcRowSetMemoryGood {

/**
 * @param args
 */
public static void main(String[] args) {
    String username = "user";
    String password = "password";
    try {
        Class.forName("com.mysql.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    JdbcRowSet jdbcRS = null;
    for (int i=0;i<150;i++){
        System.out.println(i);
        try {
            jdbcRS = new JdbcRowSetImpl(DriverManager.getConnection("jdbc:mysql://localhost/db_ams?user=" + username + "&password=" + password));
            jdbcRS.setCommand("Select * from sample_t;");
            jdbcRS.execute();
            jdbcRS.close();
            jdbcRS = null;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

}

最佳答案

问题的答案 “为什么第一个在重用连接对象时会导致内存泄漏?”

是的,您正在重用连接对象,但您在每次迭代中创建一个新的 JdbcRowSet 对象,并且不关闭它,这会导致内存泄漏。 jdbcRS = null; 不会关闭资源。

问题的答案 “为什么我不能在第一个片段集中关闭结果集,而是在第二个片段集中关闭结果集?”

在第一个代码片段中,当您使用 close 方法关闭 JdbcRowSet 对象 jdbcRS 时,jdbcRS.close(); 就关闭了连接也是如此。因此,第二次迭代将抛出 NullPointerException,因为在 jdbcRS = new JdbcRowSetImpl(connection); 处,connection 已关闭。

第二个代码片段工作正常,因为您在每次迭代中创建一个新连接 在 getConnection 方法中。

最好的方法是使用 CachedRowSet 在每次迭代后自动关闭资源:

package databases;
import java.sql.SQLException;
import javax.sql.rowset.*;

public class CachedRowSet_Usage {

    public static void main(String[] args) {
        String username = "username";
        String password = "password";
        String url = "jdbc:mysql://localhost:3306/your_database_name"; 

        try{
            CachedRowSet rs = RowSetProvider.newFactory().createCachedRowSet();
            //JdbcRowSet rs = RowSetProvider.newFactory().createJdbcRowSet();
            rs.setUrl(url);
            rs.setUsername(username);
            rs.setPassword(password);

            for(int i=0;i<150;i++){
                System.out.println(i);
                rs.setCommand("Select * from your_table");
                rs.execute();  
                //rs.close();  <-- no use, rs closes automatically
            }
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

关于java - JdbcRowSet 中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18766156/

相关文章:

mysql - 用于 JDBC/mySQL 的 Logstash 输出插件

java - 无法获得 JDBC 连接

java - Java 回车符

java - 使用 Jersey JAX-RS 时,有没有办法区分作为 null 发送的字段和根本不发送的字段?

java - Spring RMI错误java.lang.ClassNotFoundException : org. springframework.remoting.rmi.RmiInvocationHandler

java - 不将字符串列表作为单个参数传递给 preparedStatement.setObject()

java - 查找操作性能

MySQL : Updating Cells

php - mysqli_query 不再插入数据

Java(JDBC): Alternatives for iteration of query results [ while(resultSet.下一个())]