0

JdbcRowSet に大きなテーブル (約 1 万レコード) のレコードを入力しようとしています。私は2つのバリエーションを試しました(以下のコードを参照):

  1. 接続オブジェクトを作成し、 JdbcRowSetImpl(connection) を使用してインスタンス化し、クエリをループで実行します。
  2. JdbcRowSetImpl(DriverManager.getConnection("jdbc:....") を使用してインスタンス化し、クエリをループで実行します。

最初のバリエーションでは、ヒープがいっぱいになるまでメモリ リークが発生します。2 番目のバリアントにはメモリ リークがありません。接続オブジェクトを再利用するときに最初のメモリリークが発生する理由を誰かが説明できますか?

ありがとう

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();
        }
    }

}

}
4

1 に答える 1

0

あなたの質問に対する答えは、 「接続オブジェクトを再利用するときに最初にメモリリークが発生するのはなぜですか?」

はい、接続オブジェクトを再利用していますが、JdbcRowSet反復ごとに新しいオブジェクトを作成しており、それを閉じていないため、メモリリークが発生しています。はjdbcRS = null;リソースを閉じません。

「最初のスニップセットではなく、2 番目のスニップセットで ResultSet を閉じることができないのはなぜですか?」という質問に対する答えです。

最初のコード スニペットでは、 close メソッドを使用してJdbcRowSetオブジェクトを閉じると、接続も閉じます。そのため、2 回目の反復では NullPointerException がスローされます。これは、 atが既に閉じられているためです。jdbcRSjdbcRS.close();jdbcRS = new JdbcRowSetImpl(connection);connection

2 番目のコード スニペットは、メソッドの反復ごとに新しい接続を作成するため、正常に機能します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();
        }
    }
}
于 2014-06-01T14:35:23.593 に答える