2012-02-29 3 views
3

В моей заявке мне нужно указать cache данные в HashMap или TreeMap, это экономит много времени, потому что очень важно потребляющую задачу, чтобы каждый раз извлекать записи с DB server и обрабатывать их.
Я также делаю профилирование этого приложения с помощью JProfiler, и я чувствую, что, когда я получаю запись из DataBase положить в Map подключении к ResultSet и Statement не закрыто, потому что он показывает мне эти classes занимает так много памяти.
Является ли это чем-то, что я слишком остро реагирую на это или это действительно проблема?
Кстати, я закрываю connection в finally block. Я отправляю его код.Кэширование данных в HashMap (соединение, ResultSet и Statement открывается после получения данных из него и ввода карты)

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); 
    } 
} 
+3

Почему вы не используете какой-либо API кеширования, чтобы сделать это для вас более гибким и эффективным способом? –

+0

Но опять вопрос в том, почему мой профилировщик показывает эти классы DataBase, даже я их закрыл. –

+1

Вы можете показать метод 'HMDBUtil.close'? –

ответ

3

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

Кроме того, вы уверены, что метод HMDBUtil.close() работает должным образом. Это может также вызвать утечку.

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

EDIT: Просто, чтобы избежать путаницы. Классы будут присутствовать в куче до тех пор, пока вы не закончите процесс и не будете находиться в Permanent Generation.

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

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

+0

Я отслеживал это много раз, и я уверен, что после того, как GC назвал эти классы не GCed. и да, метод HMDBUtil.close() в порядке. Я принимаю Statement, Resultset и Connection как аргумент и закрываю их один за другим в методе. –

1

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

+0

Мой блок try уже выполнен. Я возвращаю карту по вышеуказанному методу, и я получаю его отлично. Это означает, что выполняется блок Try. –

+0

Но проблема, о которой вы сообщаете, - это когда вы кладете вещи на карту, не так ли? «Я чувствую, что когда я получаю записи из DataBase, чтобы подключить Map к ResultSet и Statement, они не закрыты». Это выполняется внутри try и перед закрытием. – Pau

+0

Я думаю, что я описал это неправильно, но это было похоже на то, когда я закончил работу с БД, а также этот объект находится в куче –