Für alle die nun schon ein wenig Java Luft im Notesumfeld geschnuppert haben, hier in diesem Thread ein paar Informationen zu der Problematik des Speichermanagement von Notesobjekten in Java.
Normalerweise braucht man sich bei der Java Programmierung nicht großartig um das Speichermanagement zu kümmern. Bei der Erzeugung von Objekten wird der Speicher automatisch reserviert und wenn keine Referenzen auf das Objekt mehr da sind, wird das Objekt vom Garbage Collector aufgesammelt und der Speicher wieder freigegeben. Das funktioniert in reinen JavaProgrammen wunderbar.
Leider hat aber Lotus bei der Erstellung der Notes Java Klassenbibliothek (Notes.jar) sich gedacht, wir haben ein wunderbares C++ API und warum sollen wir deshalb in Java das Rad neu erfinden. Deshalb ist die Notes.jar nur eine Hülle (Wrapper) um das darunterliegende C++ API. Dies verursacht relativ große Probleme bei der Garbagge Collection, da für jedes Notes Java Objekt (Database, view, doc usw) nicht nur das Java Objekt erzeugt wird sondern im Hintergrund eines oder auch mehrere C++ Objekte. Wenn nun die letzte Referenz auf ein Notes Java Objekt verloren geht, dann löscht der Garbage Collector zwar das Java Objekt, aber weil er von dem C++ Objekt nichts weiß bleibt dieses erhalten. Ein klassisches Memory leak (in Wirklichkeit natürlich auch ein Problem mit den handles aber meistens ist der Speicher vorher aus)
Ein Beispiel:
//Codeausschnitt natürlich nicht vollständig.
Session ses=null; //Sessionvariable definieren.
try { //Da Notes Klassen Exceptions werfen können sollte man diese auch abfangen.
ses = NotesFactory.createSession(); //Erzeugen eines Sessionobjekts
Database db=ses.getDatabase("ATARTW05/ARTWEGER/AT","mail/rpetter.nsf"); // Öffnen einer Datenbank bitte das anpassen an euer Umfeld z. B. Maildatenbank.
System.out.println("Datenbank hat folgenden Dateiname:"+db.getFileName());
}
catch (Exception e){
System.out.println("Es ist ein Fehler aufgetreten");
e.printStackTrace();
}
In dem Beispiel wird nur eine Notessession erzeugt, eine Datenbank geöffnet und der Name der Datenbank ausgegeben.
Wenn dieser Code ausgeführt wird, dann bleiben die C++ Objekte für die Session und für das Datenbank Objekt im Hauptspeicher stehen. Hier wäre das noch nicht so tragisch, doch wenn man bedenkt, dieser Codeteil käme in einer Schleife vor und würde 100 mal durchgeführt, dann wäre schon ziemlich was an Hauptspeicher verschwendet. Deshalb gibt es bei jedem Notes Java Objekt die Methode recycle() Diese entfernt von dem Notes Java Objekt die Verbindung zum C++ Objekt und gibt den Speicher des C++ Objekts frei. Dies wirkt sich nicht auf die Garbagge Collection aus. Das Java Objekt ist nachwievor da, aber man sollte tunlichst nicht mehr auf ein recycltes Java Objekt zugreifen, da es sonst zu den seltsamsten Fehlern kommt.
Als wichtige Regel beim recycle() gilt, das ein recycle das an einem übergeordneten Objekt ausgeführt wird alle abhängigen oder daraus erstellten Objekte mit recycelt. z.B. beim Recyceln einer view werden alle Dokument Objekte die aus der view erstellt wurden mit recycelt. Wenn die Session recycelt wird, dann werden alle abhängigen C++ Objekte freigegeben. Jetzt könnte man meinen das Thema wäre gegessen, das ich nur am Ende meines Programms in einem finally Block meine Session recycle(). Das funktioniert bei kleinen Programmen auch ganz gut, aber so bald man mehrere Zugriffe macht oder Dokumente in einer Schleife bearbeitet bekommt man sicher eine Out.Of.Memory.Exception oder ähnliches geworfen. Deshalb muß man auch innerhalb eines Programmes immer wieder verwendete Objekte freigeben. Ich werde in weiteren Beiträgen versuchen Beispiele für diverse Probleme beim recyceln zu geben. Denn insbesondere in Programmen mit mehreren Threads ist das teilweise nicht einfach.
Falls jemand Fragen zu dieser Materie hat, einfach nur posten,. Ich werde mich bemühen diese Fragen zu klären.
Ralf