3

在我的应用程序中,我需要输入cache数据,HashMap否则TreeMap它会节省大量时间,因为每次从中获取记录DB server并进行处理是非常耗时的任务。
我也在使用这个应用程序进行分析,JProfiler我觉得当我从中获取记录DataBase以放入Map连接时ResultSetStatement没有关闭,因为它向我展示了这些classes占用了太多内存。
这是我对此反应过度还是真的是一个问题?
顺便说一句,我正在关闭connectionin finally block。我正在发布它的代码。

public Map someFunction() throws SomeException{
Connection con=null;
    Statement stmt=null;
    ResultSet rs=null;
    String sql=null;
    Map <String,String> testMap=new TreeMap<String, String>();

    try {
        con=HMDBUtil.getConnection();
        if(cacheSize==0) {
            sql = "SELECT SOMETHING FROM SOMEWHERE";
        }else {
            sql = "SELECT SOMETHING FROM SOMEWHERE_ELSE where rownum<"+cacheSize;
        }
        stmt=con.createStatement();
        stmt.setFetchSize(100000);
        rs=stmt.executeQuery(sql);
        long count=0;
        while(rs.next()) {
            testMap.put(rs.getString(1).trim(), rs.getString(2));
            count++;
        }
    } catch (SQLException e) {

        log.fatal("SQLException while fetching Data",e);
        throw new SomeException("SQLException while fetching Data",e);          
    }finally {
        HMDBUtil.close(con, stmt, rs);
    }

    return testMap;
}

HMDBUtil.close() 方法---

public static void close(Connection con, Statement stmt, ResultSet rs)
        throws SomeException {
    if (log.isDebugEnabled())
        log.debug("Invoked");
    close(rs);
    close(stmt);
    close(con);

    if (log.isDebugEnabled())
        log.debug("Leaving");
}

所有用于关闭所有连接的关闭方法——

    public static void close(Connection con) throws SomeException {
    try {

        if (log.isDebugEnabled())
            log.debug("Invoked");
        if (con != null) {
            con.close();
            con = null;
        }

        if (log.isDebugEnabled())
            log.debug("Leaving");

    } catch (SQLException e) {
        log.fatal("SQLException while Closing connection ", e);
        throw new SomeException("SQLException while Closing connection ",
                e, false, true);
    }
}


public static void close(Statement stmt) throws SomeException {
    try {
        if (log.isDebugEnabled())
            log.debug("Invoked");

        if (stmt != null) {
            stmt.close();
            stmt = null;
        }
        if (log.isDebugEnabled())
            log.debug("Leaving");

    } catch (SQLException e) {
        // log.error("Exception while Closing statement ", e);
        log.fatal("SQLException while Closing statement ", e);
        throw new SomeException("SQLException while Closing statement ", e, false, true);

    }
}


public static void close(ResultSet rs) throws SomeException {

    try {
        if (log.isDebugEnabled())
            log.debug("Invoked");
        if (rs != null) {
            rs.close();
            rs = null;
        }
        if (log.isDebugEnabled())
            log.debug("Leaving");

    } catch (SQLException e) {
        log.fatal("SQLException while Closing rs", e);
        throw new SomeException("SQLException while Closing rs", e, false, true);
    }
}
4

2 回答 2

3

关闭连接后,结果集和语句不会立即从堆中删除。您需要至少运行一次垃圾收集器才能发生这种情况。

另外,您确定该HMDBUtil.close()方法按预期工作吗?它也可能泄漏连接。

+1 用于使用 3rd 方缓存提供程序。

编辑:只是为了避免混淆。类将存在于堆中,直到您处理结束并将驻留在Permanent Generation中。

类(对象)的实例应该被垃圾回收。如果它们不意味着您的进程以某种方式在某个地方持有对它们的引用,或者没有运行垃圾收集器。

我不确定 JProfiler,但使用 YourKit,您可以轻松导航对象图并找到哪个对象包含对未收集对象的引用。它对我过去发现内存泄漏有很大帮助。

于 2012-02-29T06:21:50.663 回答
1

最后在执行完 try 块后执行,所以当你在执行 "testMap.put(rs.getString(1).trim(), rs.getString(2));" 时是正常的 ResultSet 和 Statement 已打开,因为您尚未关闭它们。

于 2012-02-29T10:23:59.840 回答