Кэширование данных в HashMap (Connection, ResultSet и Statement открывается после получения данных из него и помещения в карту) - PullRequest
3 голосов
/ 29 февраля 2012

В моем приложении мне нужно cache данных в HashMap или TreeMap, это экономит много времени, потому что это очень трудоемкая задача - извлекать записи каждый раз из DB server и обрабатывать их.Я также выполняю профилирование этого приложения, используя JProfiler, и я чувствую, что когда я получаю записи из DataBase для подключения Map к ResultSet и Statement не закрываются, потому что это показывает мнеэти classes занимают так много памяти.Это то, что я слишком остро реагирую на это, или это действительно проблема?Кстати, я закрываю connection в 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);
    }
}

Ответы [ 2 ]

3 голосов
/ 29 февраля 2012

Результирующий набор и оператор не будут удалены из кучи сразу после закрытия соединения. Для этого нужно иметь хотя бы один запуск сборщика мусора.

Кроме того, вы уверены, что метод HMDBUtil.close() работает, как ожидалось. Также может произойти утечка соединения.

+ 1 для использования стороннего поставщика кэширования.

РЕДАКТИРОВАТЬ : Просто, чтобы избежать путаницы. Классы будут присутствовать в куче, пока вы не завершите обработку, и будут находиться в Permanent Generation .

Экземпляры классов (объектов) должны собираться мусором. Если это не так, это означает, что ваш процесс каким-то образом хранит ссылки на них, или сборщик мусора не был запущен.

Я не уверен насчет JProfiler, но с помощью YourKit вы можете легко перемещаться по графу объектов и находить, какой объект содержит ссылки на несобранные объекты. Это очень помогло мне найти утечки памяти в прошлом.

1 голос
/ 29 февраля 2012

Наконец, выполняется после выполнения блока try, поэтому нормально, когда вы выполняете "testMap.put (rs.getString (1) .trim (), rs.getString (2));" ResultSet и Statement открыты, потому что вы еще не закрыли их.

...