Autor Thema: Speichermanagement im Notes Java Umfeld  (Gelesen 5273 mal)

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Speichermanagement im Notes Java Umfeld
« am: 26.06.03 - 16:02:36 »
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
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Offline Rob Green

  • Freund des Hauses!
  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 2.651
  • Geschlecht: Männlich
    • Meipor
Re:Speichermanagement im Notes Java Umfeld
« Antwort #1 am: 26.06.03 - 18:23:37 »
dazu eine Frage, wenn sie sich auch evtl. komisch anhört (das sind Anfängerfragen immer): wenn ich das recycle verwende und zB das innerhalb eines Java Agents auf dem Domino Server nutze (weil Java Agents eben gethreaded werden und nur einmal in den Speicher geladen werden, statt ein normaler WebQueryOpen auf LS Basis, der immer wieder bei jedem HTTP Request geladen wird), wirkt sich das Recycle auf den aktuellen ThreadProzess eines Users aus oder kollidiert das mit parallelen Threads des gleichen Java Agents? Ich hoffe, es ist klar, was ich meine. Sprich: ist eine recycle Anweisung  threadmäßig abgeschottet oder nicht?
Vielleicht verdirbt Geld wirklich den Charakter.
Auf keinen Fall aber macht Mangel an Geld ihn besser.
(John Steinbeck)

Meiporblog: http://www.meipor.de/blog
allg. Unternehmerblog: http://www.m-e-x.de/blog

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Re:Speichermanagement im Notes Java Umfeld
« Antwort #2 am: 26.06.03 - 18:57:54 »
Das ist keine einfache Frage, vor allem kann ich nicht ganz glauben, dass Java Agents so funktionieren wie du es beschreibst, kann es sein, dass du diese mit Servlets verwechselst?  Ok aber zu deiner Frage mit den Threads Wenn du das gleiche Notes Java Objekt in zwei verschiedenen Threads verwendest verwenden auch beide Threads im Hintergrund das selbe C++ Objekt. Wenn du nun in einem der Threads recycle aufrufst, kannst du das Objekt auch im anderen Thread nicht mehr verwenden. Eine Ausnahme ist es wenn du in jedem Thread ein eigenes Session Objekt erstellst, dann verhalten sich alle Threads vollkommen eigenständig und du kannst beliebig recyclen. Aber vorsicht, versuche dann nicht von einem Thread auf Objekte aus dem anderen Thread zuzugreifen, denn sonst bekommst du ein totales Durcheinander.

Grüße

Ralf
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Offline Axel_Janssen

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 769
Re:Speichermanagement im Notes Java Umfeld
« Antwort #3 am: 26.06.03 - 23:19:17 »
Das ist keine einfache Frage, vor allem kann ich nicht ganz glauben, dass Java Agents so funktionieren wie du es beschreibst, kann es sein, dass du diese mit Servlets verwechselst?  

ich würde sagen ja.
Klassischer Fall von unintendierten Thread Hyjacking. 8)
Ich tue das in einen eigenen Diskussions-Thread:
Servlets, Notes-Agents, Java-Programme die auf Notes zugreifen und diese merkwürdigen Threads.
@Rob: Ich liebe solche Querschläger. Ohne jede Häme.
Es gab mal eine Zeit auf meinem anderen Forum (ihr wisst schon), wo Peter den Haan Antworten auf 70% meiner Beiträge mit "Oh boy," einleitete.  ;D

@Ralf: Warum haben die die Notes-Java-Klassen nicht so implementiert, dass im finalize() recycle() aufgerufen wird bzw. die haben das bestimmt gemacht? Warum macht das Probleme? Dort könnte man den JNI-code unterbringen, der den Speicher der C-Objekte freigibt. Da gibt es sicher noch ein paar Subtilitäten.
{
erklärung: Jede Java-Klasse hat eine finalize() - Methode. Wenn sie nicht explizit in der Klasse steht, ist sie trotzdem da, weil sie in java.lang.Object steht und jede Klasse erbt von java.lang.Object.
Die finalize()-Methode eines Java-Objekts wird vom Garbage-Collector garantiert aufgerufen, bevor es garbage-collected wird.
}  
Hier ist ein kurzer Artikel zu garbage-collection in plain-english:
http://www.jchq.net/certkey/0301certkey.htm

Axel
« Letzte Änderung: 27.06.03 - 00:35:25 von Axel_Janssen »
... design patterns are abstract designs that help identify the structure and elements involved in a specific design solution. From this, a concrete implementation can be produced.
Kyle Brown

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Re:Speichermanagement im Notes Java Umfeld
« Antwort #4 am: 27.06.03 - 07:41:38 »
@Axel

Ja das ist schon klar, andere machen das ja auch so, aber Lotus ist dabei offensichtlich auf Irgendein Problem gestossen, hat dieses Sun gemeldet und Sun hat gesagt als Umgehung des Problems soll Lotus die C++ Klassen durch Native Java ersetzen. Das wollte natürlich Lotus wieder nicht. Ein Problem ist, dass beim lokalen Zugriff  also nicht über DIIOP für jede Verwendung der C++ Objekte der Thread für Notes initialisiert sein muß. Wenn aber  nun in der finalize() Methode das recycle aufgerufen wird, kann nicht sicher gewärleistet werden, ob der Thread für Notes initalisiert ist.

Aber langer Rede kurzer Sinn, Lotus hat es so implementiert und wir können es nicht ändern. Nur so gut als möglich damit leben.

Übrigens nicht von recycle abschrecken lassen, wenn man es von Anfang an, bei der Entwicklung berücksichtigt, dann ist es relativ leicht zu beherrschen. Schwierig ist es wenn man es nachträglich einbaut.

Grüße

Ralf
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Offline datenbanken24

  • Senior Mitglied
  • ****
  • Beiträge: 390
  • Geschlecht: Männlich
  • Stammgast
    • datenbanken24
Re:Speichermanagement im Notes Java Umfeld
« Antwort #5 am: 14.08.03 - 01:17:09 »
Wir nutzen für unseren Internetservice
datenbanken24.de
mehrere Domino 6.01 CF1 Server auf Suse 8.1
auf Rootservern bei Puretec.

Ich habe die Diskussion über Java gc Speicherprobleme hier im Forum gelesen und versuche nun herauszufinden, ob dies der Grund für ein Problem auf einem unserer Server sein könnte:

Auch wir haben auf einem unserer Testserver Java-Agenten zu laufen, die NICHT programmiert "recyclen".
Der Server selbst läuft gleichmäßig performant und fehlerfrei, stürzt aber in unwillkürlichen Abständen von 7-14 Tagen komplett ab und zieht das Linux mit runter.
Alle Fehlersuche war bisher vergeblich - die Abstürze sind weder an bestimmte Ereignisse noch vom jeweiligen Traffic abhängig. Alle Logs sind unauffällig.

Folgende Frage:

Wenn die Java Agenten ohne Recycling den Speicher belegen, würde man das über ein Ansteigen der Swap-Datei bemerken?
Die Swap-Datei ist nie zu mehr als ca. 175.000 von 750.000 MB ausgelastet.

Oder belegen diese unsauberen Java-Agenten auch Threads?
Der Serverabsturz kommt meist 1-2 Tage nach mehrfachem Lauf dieser Agenten - nicht aber während die Agenten laufen.

Wenn man davon ausgeht, daß der Domino-Server unter Linux standardmäßig nur 1.000 Threads handeln kann - und die vielleicht durch die Java-Agenten irgendwann voll sind...
Ist so etwas vorstellbar?

Können also unsaubere Java-Agenten dazu führen, dass der Server erst (viel) später abstürzt - ohne daß der Swap voll ist ?


Uwe
MANETU KG
http://www.datenbanken24.de

Offline Axel_Janssen

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 769
Re:Speichermanagement im Notes Java Umfeld
« Antwort #6 am: 14.08.03 - 03:34:36 »
Wenn die Java Agenten ohne Recycling den Speicher belegen, würde man das über ein Ansteigen der Swap-Datei bemerken?
Die Swap-Datei ist nie zu mehr als ca. 175.000 von 750.000 MB ausgelastet.

Oder belegen diese unsauberen Java-Agenten auch Threads?
Der Serverabsturz kommt meist 1-2 Tage nach mehrfachem Lauf dieser Agenten - nicht aber während die Agenten laufen.

Wenn man davon ausgeht, daß der Domino-Server unter Linux standardmäßig nur 1.000 Threads handeln kann - und die vielleicht durch die Java-Agenten irgendwann voll sind...
Ist so etwas vorstellbar?

Können also unsaubere Java-Agenten dazu führen, dass der Server erst (viel) später abstürzt - ohne daß der Swap voll ist ?


Uwe
MANETU KG
http://www.datenbanken24.de

Hi Uwe,

für mich sind diese Lotus-RPC Sachen, die von den Java-Wrappern angesprochen auch noch eine black box. Ich kenne mich dazu zu wenig mit der inneren Funktionsweise von Lotus-RPC aus.
Ich seh es aber nicht memory leak Problem, wo langsam aber sicher der Heap Speicher immer mehr belegt und nicht freigegeben wird.
Die Größe der Auslagerungsdatei wäre somit kein zuverlässiger Indikator.

Es erinnert am Verhalten vielmehr an Situationen wo ich RDBMS-Datenbank-Connections nicht schließe. Das führt auch irgendwann zum großen Chaos.

Durch recycle() werden die Client RPC-stubs (weiß nicht, ob das überhaupt Objekte sind und auch nicht ob stubs das richtige Wort ist
 ::) ) jedenfalls zuverlässig in einen stabilen Ausgangszustand zurückgesetzt. Ohne recycle() eben genau nicht. Keine Ahnung. Vielleicht werden da irgendwelche Semaphore über die RPC handles gelegt und es gibt nur eine endliche Anzahl von benutzbaren stubs, aber das ist reine Spekulation.

Das einzige was ich aus meiner Testerfahrung sagen kann ist, daß recycle stabil funktioniert. Dies in den code der Agenten einzubauen ist auch relativ unproblematisch, wenn man genau drüber nachdenkt. Gehe einfach alle Möglichkeiten (inklusive catch Block durch) und du bist die Probleme los.

Mit Threads dürfte das wenig zu tun haben, da Lotus IMHO threads gar nicht kennt (jeder Agent --> und der gewrappte RPC-code dürfte wie ein Agent arbeiten, belegt einen Prozeß (kann mich aber hier irren und bewege mich auf relativ dünnen Eis)).

Du hast mich auf eine gute Idee gebracht. Ich werde auf meinen code mal 100.000 sequentielle Zugriffe mit Zufallsdaten machen. Mit und ohne recycle. Poste dann. Bei Ralf seiner Firma läuft das ja in Produktion und auf der Website, also dürte es mit recycle() zuverlässig funktionieren.

Gruß Axel
« Letzte Änderung: 14.08.03 - 03:58:31 von Axel_Janssen »
... design patterns are abstract designs that help identify the structure and elements involved in a specific design solution. From this, a concrete implementation can be produced.
Kyle Brown

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Re:Speichermanagement im Notes Java Umfeld
« Antwort #7 am: 14.08.03 - 08:23:16 »
Hm bei Agenten ist das mit dem recyceln so eine Sache. Denn in normalen Java Programmen  kann ich am Schluß die Session recyceln wodurch alle anderen Objekte auch ziemlich zuverlässig automatisch mitrecycelt werden. Bei Agents darf man aber auf keinen Fall die Session oder den AgentContext recyceln. Da die Grundregel beim recyceln ist, dass nur diese Objekte recycelt werden dürfen, die auch vom Benutzer erstellt wurden. Session und AgentContext werden von Notes in Agenten automatisch bereitgestellt. Deshalb solltest du jedes von dir erstellte Objekt auf jeden Fall händisch recyceln.  Du schreibst, dass du nichts auffäliges in den logs finden kannst. Was steht denn in den Logs?

Grüße

Ralf M Petter
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

 

Impressum Atnotes.de  -  Powered by Syslords Solutions  -  Datenschutz