Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не высвобождается память при работе с БД, в работе с БД H2 не освобождается память 
V
    Опции темы
Alexander06
Дата 23.11.2008, 21:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 90
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Здравствуйте.
Я пишу приложение на Java, работающее с базой данных H2.
Сайт СУБД
Работа ведется в режиме embedded.

Осуществляю загрузку данных из текстового файла в БД. При добавлении записи каждый раз проверяю наличие аналогичной, думаю по-этому, с ростом таблицы, размер выделенной памяти растет.
Но после завершения функции и даже закрытия соединения с базой, выделенная память не освобождается.

Надо заметить, что иногда использую конструкции вида:

Код


    public int getInt(String rowName){
        try {
            return this.rs.getInt(rowName);
        } catch (SQLException ex) {
            return -1;
        }
    }

    public int getNodeKey(String name) {
        ResultSet oldRS = this.rs;
        int res;
        this.querySQL("SELECT key FROM nodes WHERE name = '" + name + "' LIMIT 0, 1");
        if (this.next() == true) {
            res = this.getInt("key");
        }else{
            res = -1;
        }
        this.rs = oldRS;
        return res;
    }


, где rs - объявлена как public ResultSet rs; в классе, работающим с БД.

То есть при вызове функции сохраняю предыдущий ResultSet с тем, чтобы потом его вернуть обратно. Насколько я понимаю, полученный в запросе ResultSet должен в последствии быть собран сборщиком мусора.
Пробовал принудительно вызывать сборщик после закрытия БД - не помогает.
Подскажите, как отследить утечку памяти? Использую IDE NetBeans 6.5, там есть утилита Profiler.
В результате работы приложение вызывает превышение максимального размера кучи с результатами выделения памяти:

org.h2.result.SimpleRowValue - 23%
org.h2.result.Row                    - 20%
java.lang.Object[]                    - 11%
char[]                                       - 10%
org.h2.Value.ValueString         - 9%
org.h2.Value.ValueInt              - 9%
org.h2.Value.Value[]                - 9%
org.h2.Result.Row                   - 9%

такое впечатление, что результаты выполнения запросов не удаляются из памяти, а остаются в ней.

Если что-то осталось не ясным, спрашивайте, постараюсь уточнить.
Заранее спасибо.
PM MAIL   Вверх
powerOn
Дата 23.11.2008, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


software saboteur
****


Профиль
Группа: Участник
Сообщений: 4367
Регистрация: 7.10.2005

Репутация: 47
Всего: 159



может там кэш такой суровый?


--------------------
user posted image нет времени думать - нужно писать КОД!

PM MAIL   Вверх
Alexander06
Дата 24.11.2008, 01:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 90
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Возможно. Я попробовал уменьшить его - занимаемая память сократилась.
Работать уже можно, с сообщениями о превышении допустимого размера не вылетает, хотя память продолжает засоряться.
Получается, что в итоге прийду к тем же результатам, только позже.
Но ваш совет полезен, спасибо.
Может быть есть какие-то правила, чего стоит избегать для своевременного освобождения памяти?
PM MAIL   Вверх
COVD
Дата 24.11.2008, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата

То есть при вызове функции сохраняю предыдущий ResultSet с тем, чтобы потом его вернуть обратно.


Это, мягко говоря, сомнительная затея. 

Цитата

Насколько я понимаю, полученный в запросе ResultSet должен в последствии быть собран сборщиком мусора.


Все что вам нужно, это извлечь из ResultSet'a интересующие вас данные. Обычно резалтсет обьявляют локально, т.е. ссылка на него существует только внутри метода во время извлечения данных. 
Как-то так 

Код

ResultSet rs = connection.executeQuery(...
while(rs.next()){
    ... = rs.getInt(..
}



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

    

Это сообщение отредактировал(а) COVD - 24.11.2008, 17:25
PM MAIL   Вверх
Alexander06
Дата 24.11.2008, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 90
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Я выделил отдельный класс для выполнения запросов к БД.
В нем создал поле ResultSet rs с тем, чтобы использовать в конструкциях вида 
Код

ResultSet rs = connection.executeQuery
while(rs.next()){
    ...
}

в методах этого класса.

Дело в том, что некоторые функции требуют запросить данные из таблицы, а потом для каждой из них выполнить несколько запросов.
Поэтому я специально сохраняю старый ResultSet, чтобы не терять результаты внешнего запроса при выполнении внутренних. Я решил, что копировать куда-то результаты из ResultSet, это лишняя работа.
Попробую последовать вашему совету. Спасибо.
PM MAIL   Вверх
COVD
Дата 24.11.2008, 20:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 17
Всего: 43



Цитата

Поэтому я специально сохраняю старый ResultSet, чтобы не терять результаты внешнего запроса при выполнении внутренних.
 

Очевидно, для "внешних" и "внутренних" запросов вы используете разные соединения, т.е. вы держите открытыми несколько соединений к БД. Возможно, последовательное извлечение данных через одно соединение проще программировать.
PM MAIL   Вверх
Alexander06
Дата 25.11.2008, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 90
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Соединение использовал одно, устанавливаемое в начале работы программы.
Правда каждый раз выполнял createStatement() перед выполнением запроса, это я убрал, работает.
Сейчас программа постепенно выбирает определенную квоту памяти и дальше практически не растет. Наверное это кэш БД.
Может где-то и есть утечки, но они не очевидны.
Всем спасибо smile 

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0478 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.