Сборка мусора в Lotus

vincent_vega

Green Team
02.04.2005
169
1
BIT
0
Проблема агентов в Лотусе только одна - нужно писать правильный код и правильно чистить за собой мусор. Если этого не делать, то таки да, будут проблемы с подвисанием сервера. Но если сделать все правильно то проблем не будет.

Вот нашел, уже писал когда-то пример на этом форуме:
Java:
import lotus.domino.*;

public class Temp extends AgentBase {
    
    //Хорошая реализация
    public void V1() {
        ViewEntry entry = null;
        ViewEntryCollection col = null;
        Document doc = null;
        View view = null;
        
        try {
            col = view.getAllEntries();
            int appCount = col.getCount();
            for (int i = 1; (i <= appCount); i++) {
                entry = col.getNthEntry(i);
                doc = entry.getDocument();
                // ....
                doc.recycle();
                entry.recycle();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // Плохая реаллизация. Утечка памяти
    public void V2() {
        Document doc = null;
        View view = null;
        
        try {
            doc = view.getFirstDocument();
            while (doc != null) {
                // ...
                doc = view.getNextDocument(doc);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}
 
R

RixPvl

Извиняюсь за возможно глупый вопрос, а чем это может помочь? Просто я яву начал только учить и возможно много еще не знаю. :)
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
472
нотусёвые объекты достаточно объемны, и сборка мусора вызывается несколько отличным образом от "обычной" jvm
выше упоминали - размер кучи (да и стека) jvm ограничены (дефолтно - "небольшим" значением), в LS они ограничены только размером свободной памяти процесса (до 2Гб)
 
30.06.2006
141
5
BIT
0
В Java с памятью надо быть аккуратнее, т.к. каждый раз когда выполняется doc = view.getNextDocument(doc), то создается новая переменная, под которую выделяется память.
Т.е. если в представлении будет 1000 документов, то к концу цикла у тебя будет выделено памяти под 1000 переменных типа Document.
Поэтому перед очередным присвоением необходимо освобождать память, которую занимает переменная.

Посмотри в хелпе описание метода getNextDocument - там сказано про освобождение памяти.
 
R

RixPvl

Подскажите все ли правильно сделал (по очищению объектов)? вроде как все сделал а памяти отъедает как не знаю кто, за каждый запуск по 5-10% и причем после завершения агенте память не возращается, видно все еще висит в памяти, как решить и что делать уже и не знаю...
 
R

RixPvl

Тут почитал не знаю правильно ли понял людей, но есть функция System.gc() которая запускает очистку кучи, стоит ли использовать?
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
233
Говорили же, что надо recycle. Везде используется = null, а оно как мёртвому припарка.

Я в секции finally{ ... } чищу все поля-объекты класса и некоторые объекты в агентах, - особенно SWT-объекты на локале, т.к. не почистишь, в следующий раз агент не запустится.
И в каждом методе стараюсь смотреть, если объект при выходе из метода не будет использоваться, то стараюсь его грохать (метод recycle + null, если recycle не поддерживается, то просто = null).
Всё это делаю в основном для объектов собственных классов, для всех Lotus-объектов, поддерживающих recycle и для Java-объектов, содержащих большие объёмы данных, как то коллекции, векторы и т.п.
Не знаю, может ещё кто-нибудь что-то подскажет.
 
R

RixPvl

Код:
					ntTmp = doc;
doc = null; <--- если тут делать recycle, то цикл завершается и дальше не идет, причем ошибок ни каких нет
doc = view.getNextDocument(ntTmp);
ntTmp.recycle();
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
233
RixPvl сказал(а):
+ сделал изменение при переборе клекции по аналогии из хелп лотуса
Надо делать так (модифицированный код из хелпа, предотвращающий все возможные утечки):
Java:
Document doc, tmpdoc = null;

View view = ...;        // получение вида
try {
    while (doc != null) {
        try {
            System.out.println(doc.UniversalID + ": " + doc.getItemValueString("Subject"));
          
            // Your code
          
            tmpdoc = view.getNextDocument(doc);
        }
        finally {
            if (doc != null) doc.recycle();
        }
        doc = tmpdoc;
    }
}
finally {
    if (tmpdoc != null) tmpdoc.recycle();
    if (view != null) view.recycle();
}
У меня работает.
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
472
принудительный вызов gc никчему адекватному не приведёт :rolleyes:
при это не надо забывать, что ИБМ по-своему реализует gc
освобождение (recycle) нотусёвых объектов крайне желательно, ибо... они (объекты) связаны с нативным кодом, а "такие" объекты могут не освобождаться при сборке
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
233



Добавлено: рабочий код находится здесь.
 
N

nvyush

а tmpdoc убивать ненадо?
Не путайте объект и указатель на объект
Java:
tmpdoc = view.getNextDocument(doc);    //создаём объект для следующего документа и присваиваем его адрес указателю tmpdoc
doc.recycle();    //утилизируем объект документа, на который указывает doc
doc = tmpdoc;    //присваиваем указателю doc адрес, на который указывает tmpdoc
//  tmpdoc.recycle();    //этим действием будет уничтожен объект, на который указывают и tmpdoc и doc
 
K

Kee_Keekkenen

И в нашей Википедии
если что-то хочешь найти про очистку, то именно выше описанное во всех статьях и пишут..

а вообще очистка (вплоть до итемов) очень помогает джаве не падать..

как вы думаете, что будет если сделать так:
<!--shcode--><pre><code class='java'>doc.replaceItemValue( "test", "1" ).recycle();
doc.getItemValueString( "test" );[/CODE]а самое главное почему ?! с документом иначе получается..
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
233
как вы думаете, что будет если сделать так:

doc.replaceItemValue( "test", "1" ).recycle();
doc.getItemValueString( "test" );

а самое главное почему ?! с документом иначе получается..
Не пробовал, но думаю, что:
- после первой строки ничего особенного не произойдёт, т.к. replaceItemValue возвращает объект, аналогичный NotesItem'у, по значению, который поддерживает recycle;
- 2-я строка также прекрасно отработает, т.к. она не работает с тем Item-объектом, который был возвращён и ЗАrecycleН, т.е. берётся из дока заново.

Это то же самое, что в LS получить объект NotesItem, сделать ему Delete, а потом выполнить getItemValue.
 
K

Kee_Keekkenen

принудительный вызов gc никчему адекватному не приведёт wink.gif

не соглашусь.. как раз наоборот принудительный вызов очищает память..
что касается лотуса, то в нем все нормально работает, если мега процесс разбить на подпроцессы и вызывать их последовательно, чередуя с вызовом gc..

не так давно написали красивый конвейер для выполнения обработки данных, который реализовал выполнение всего трех схем (с контролем эксцепшионов и рестартом с места падения, отчетностью по выполнению), в каждой из которых было по 5-7 действий.. в результате, даже при тотальной чистке объектов все равно не хватало памятульки и где-нибудь вылетало, при чем вылеты были двух типов:
1. после makeresponce копировалось поле $REF, так оно не копировалось, хотя было в докумиенте - это отлавливаемый эксцепцион (ругалось на то, что объект был удален или рециклен)
2. где-то произвольно код вылетает и никаких эксцепшионов нет - просто остановка выполнения кода

так вот, после того, как каждое действие (вызов выполнения) было вынесено в отдельный агент, и после каждого запуска агента-действия, вызывается агент с gc, все стало просто зело предивно работать..
 
K

Kee_Keekkenen

Не пробовал, но думаю, что:
- после первой строки ничего особенного не произойдёт, т.к. replaceItemValue возвращает объект, аналогичный NotesItem'у, по значению, который поддерживает recycle;
- 2-я строка также прекрасно отработает, т.к. она не работает с тем Item-объектом, который был возвращён и ЗАrecycleН, т.е. берётся из дока заново.

Это то же самое, что в LS получить объект NotesItem, сделать ему Delete, а потом выполнить getItemValue.

:D я тоже так думал, однако java-парадигма ломает документ идею лотуса :)
итем это джава объект, если ему сделать рецикл, то ниточка покоторой можно получить поле из документа изчезнет - ништяк (в плохом смысле)..
технически выглядит как-будто было сделано removeItem.. поле будет доступно, только поле переполучения документа, если, конечно, было сохранение, правда клево ?!..

Добавлено:

тут не ясно что имеется в виду, т.к. неизвесно как там в этой доминге все устроено в плане утилизации..
 

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
233
Kee_Keekkenen
"Ну... значит моя версия была ошибочной" © :)

P.S. Нет, не была ошибочной - вышеуказанный код:
Java:
doc.replaceItemValue("test", "1").recycle();
System.out.println(doc.getItemValueString("test"));
прекрасно работает.
 
Последнее редактирование:

VladSh

начинающий
Lotus Team
11.12.2009
1 797
158
BIT
233
Ещё раз решил вернуться и написать правильную конструкцию, которая почти полностью гарантирует отсутствие утечек:
Java:
//здесь инициализация объекта
try {
    //здесь работа с объектом
}
finally {
    //здесь recycle, если объект != null
}
Единственный вариант с утечкой возможен, если в try кто-то по глупости присвоил объекту null...
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!