Deshalb gilt folgender Merksatz: Jedes Notesobjekt soll so rasch als möglich wieder recycelt werden. Spätestens jedoch bevor es derefenziert wird.
Ein Beispiel:
if(flag) Document doc=view.getFirstDocument(); System.out.println(doc.getItemValueString("Test"); }
Die Variable doc ist nur innerhalb des ifs gültig und muss deshalb noch innerhalb des if's recycelt werden.
if(flag){ Document doc=view.getFirstDocument(); System.out.println(doc.getItemValueString("Test"); doc.recycle(); }
Es gibt beim Recycle jedoch eine Erleichterung, die einem einige Arbeit spart. Das recyceln von übergeordneten Objekten recycelt alle abgeleiteten Objekte mit.
Auf unser Beispiel übertragen:
View view=cdb.getView("Test"); if(flag){ Document doc=view.getFirstDocument(); System.out.println(doc.getItemValueString("Test"); // doc.recycle(); kann man sich sparen, da das Dokument beim Recyclen der View mitrecycelt wird } else{ Document doc=view.getLastDocument(); System.out.println(doc.getItemValueString("Test"); // doc.recycle(); kann man sich sparen, da das Dokument beim Recyclen der View mitrecycelt wird } view.recycle();
Man sollte dieses implizite Recycle aber nur dann verwenden, wenn man wie in unseren Beispiel gewährleisten kann, dass nur sehr wenige Objekte erzeugt werden und diese auch nicht mit der Datenmenge mehr werden.
Fatal wäre folgender Code:
View view=cdb.getView("Test"); Document doc=view.getFirstDocument(); while(doc!=null){ //Mach was mit doc doc=view.getNextDocument(); } view.recycle();
Dieser Code wird spätestens, bei ein paar Hundert Dokumenten in der View crashen.
Man muß also doc bei jedem Schleifendurchlauf recyceln. Das ist jedoch nicht ganz einfach, da doc ja nach getNextDocument nicht mehr da ist und vorher darf ich es nicht recyclen, da sonst getNextDocument() nicht mehr funktioniert, wenn das aktuelle Dokument recycelt wird. Folgendes Pattern hat sich bewährt:
View view=cdb.getView("Test"); Document doc=view.getFirstDocument(); while(doc!=null){ //Mach was mit doc Document tempdoc=doc; doc=view.getNextDocument(); tempdoc.recycle(); } view.recycle();
Aufpassen muß man natürlich auch darauf, dass man nicht Objekte implizit bereinigt die man noch gerne verwenden möchte:
View view=cdb.getView("Test"); Document doc=view.getFirstDocument(); view.recycle(); //Hier wird doc implizit mitrecycelt. Man darf doc nicht mehr verwenden. System.out.println(doc.getItemValueString("form")); //Hier wird das Programm crashen.
Ich hoffe etwas Licht in die Sache gebracht zu haben. Würde mich auch über Kommentare zu spezifischen Problemen freuen, die ich dann im 3. Teil behandeln werde.
danke für die erhellenden Worte, ich habe vorher immer eher zuviel als zuwenig recycelt, habe Dank Deiner Ausführungen aber jetzt viel klarere Vorstellungen.
ReplyDeleteWas mache ich mit den internen Objekten einer function, die ein Notesobjekt zurückgeben?
Beispiel:
Agent ruft function auf mit einem keystring, der über in der function definierte db, view, doc - Kette ein Richtextiten zum anhängen an ein im Agent erzeugtes document zurück gibt?
Ist nicht mein Code, aber jetzt mein Problem ;-)
Die darfst du nicht recyceln, da du sonst das Richtextitem mitrecyceln würdest. Solche Konstrukte solltest du meiden wie der Teufel das Weihwasser. Am besten ist es du übergibst das Doc an dem das Richtextitem angehängt werden soll als zusätzlichen Parameter an die Funktion. Dann kannst du nach dem Anhängen in der Funktion aufräumen.
ReplyDeleteDanke Ralf, very Cool deine Erklärung, ich habe leider mit anderen Probleme zu kämpfen
ReplyDeletewir haben 2 Anwendungen auf was6 die Notes Connections verwenden,
leider haben wir ab und zu mal hängenden notesThreads die wir nicht erklären können.
auf Entwicklung und QS System und lauft alles wunderbar, beim Kunde nie richtig , die mussen immer wieder den Was6 starten. wir haben wochen lang den Code geprüft. aber nothing
System is 1 zu 1 Konfiguration auch. vielleicht hast du ein Tipp wo ich suchen könnte
Thanks
Verwendet ihr den lokalen Zugriff? Sprich macht ihr bei jedem Zugriff ein NotesThread.sinitThread und beim Beenden eine NotesThread.stermThread? Wir hatten früher auch WAS 6 im Einsatz und diverse Probleme mit Abstürzen. Wir haben dann lange mit WAS und Lotus Experten das Problem analysiert und vom WAS Team die Empfehlung bekommen, dass man Threads nur einmal initialisieren soll und nicht bei jedem Zugriff. Das WAS Team hat uns dann sogar einen Fix zur Verfügung gestellt, mit dem es möglich was Threads wieder sauber herunterzufahren. Das war aber bei uns gar nicht nötig.
ReplyDeleteDanke für die Antworkt Ralf,
ReplyDeletewir initialisieren nur 1 mal, ich denken wir haben probleme mit der Notes.jar und Classloader,
im momement binden wir die notes.jar als shared library. und wir haben ein classloader für den Server d.h die Anwendungen sid mit parent_first eingestellt
l.g