簡體   English   中英

JdbcRowSet中的內存泄漏

[英]Memory Leak in JdbcRowSet

我嘗試用大表中的記錄(約一萬條記錄)填充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; 不會關閉資源。

您的問題的答案 “為什么我不能在第一個摘要中關閉ResultSet,而在第二個摘要中?”

在你的第一個代碼段,當你關閉JdbcRowSet對象jdbcRS使用close方法, 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();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM