Wenn OutOfMemoryErrors geworfen werden, sollte der
Benutzer das mitkriegen (in einer schönen bunten Box,
wer kuckt schon ins error-log), denn im schlimmsten
Fall kann das zu verstümmelten Reports führen!
Das geht so einfach leider nicht. Zum einen handelt es sich
dabei um einen Error und keine Exception, so das sie
normalerweise nicht gefangen werden sollte. Ist in diesem
Fall auch nicht sinnvoll, weil man damit nichts machen kann,
weil eben kein Speicher mehr zur Verfügung steht (eine
Anzeige per Dialog fällt somit z.B. aus).
Das die Meldung im Log steht liegt vermutlich daran, weil
alles, was nach System.err/System.out geschrieben wird im
log landet. Das wird automatisch von Java gemacht, wenn der
Fehler auftritt. Normalerweise stürzt eine Anwendung dabei
ab (genauer: der ausführende Thread stürzt ab). Es gibt
normalerweise keine vernünftige Möglichkeit dieses Problem
zu detektieren und darauf zu reagieren. Ich glaube, man kann
ihn nicht einmal per try() catch() fangen, da dabei eine
Variable zugewiesen werden soll, was wieder Speicher
verbrauchen würde, den man ja aber gar nicht zur Verfügung
hat. Ein OutOfMemoryError ist so ziemlich das böseste, was
einem passieren kann. Leider wird er von Java auch dann
geworfen, wenn die Vorraussetzung (kein Speicher mehr
verfügbar) gar nicht wirklich zutrifft. Das kann man
allerdings verhindern, indem man den Finalizer-Thread von
Java mit höchster Priorität laufen läßt (Ich mail Fiete mal
die entsprechenden Code-Zeilen, die dafür nötig sind).
Derethor
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
magellan leitet system.err system.out in das log um...(client.java)
Zu den Zeilen von Derethor aka Helge frag ich ihn direkt noch....provided as is kann ich damit noch zu wenig
anfangen..-,))
In einem anderen Leben hatte ich mal versucht, den noch freien Speicher zu prüfen und wenn der zu gering wurde,
habe ich (damals) den garbage collector angeworfen, und wenn das nicht gereicht hat, mit Fehlermeldung
prophylaktisch abgebrochen....
FF
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ich habe ja auch nicht gesagt, dass es einfach wäre ;)
Also erstens: Doch, man kann auch OOMErrors abfangen.
Zweitens: Nur in der Theorie steht danach kein Speicher zur
Verfügung. Wenn man den Fehler weit genug oben abfängt, ist
in der Regel auch wieder Speicher freigeworden, oder?. Ich
hatte schon zahlreiche OOMErrors, aber selten ist Magellan
deswegen abgestürzt. Drittens: Wir brauchen ja nicht
unbedingt eine perfekte Fehlerbehandlung, es reichen erst
mal die typischen Fälle. Speicher wird vor allem gebraucht
beim Lesen und beim Schreiben von Reports. Dann noch
überall, wo User-Interface aufgebaut wird. Ersteres sollte
relativ leicht zu behandeln sein, Letzteres ist etwas
schwieriger. Noch zwei Beispiele aus meiner errors.txt:
Exception on Toolkit thread: java.lang.OutOfMemoryError:
Java heap space
java.lang.OutOfMemoryError: Java heap space
Exception in thread "AWT-EventQueue-0"
java.lang.OutOfMemoryError: Java heap space
Exception in thread "AWT-EventQueue-0"
java.lang.OutOfMemoryError: Java heap space
Zusatzfrage (für 2 Extrapunkte): Ist es möglich, der JVM vom
Programm aus mehr Speicher zuzuweisen? Vermutlich nicht.
Dann sollten wir zumindest (wieder?) eine
magellan.bat/magellan.sh zur Verfügung stellen, die java mit
mehr als dem Standard von 64MB aufruft.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ich habe nicht gesagt, das man den nicht abfangen kann,
allerdings SOLLTE man es nicht tun. Ein Error ist ein
schwerwiegendes Problem, das man in der Regel nicht mehr
behandeln kann. Magellan ist unter Umständen nicht
abgestürzt, aber der Thread, der gerade ausgeführt wurde
(Beim Ausführen eines Kommandos wird von der Oberfläche ein
Thread gestartet, der die eigentliche Methode aufruft damit
die Oberfläche nicht blockiert). Deshalb bleibt die
Oberfläche bestehen, aber der Thread (und alle Daten die in
seinen Kontext gehören, und da gehört auch der Error dazu)
sind dann weg.
Allerdings wirft Java, wie schon erwähnt auch einen OOM,
wenn dies eigentlich falsch ist. Dazu muß man wissen, das
Der gc NICHT für freien Speicher sorgt, sondern das er
Objekte als freizugeben markiert. Der Speicher gilt erst als
freigegeben, wenn der Finalizer-Thread diese markierten
Objekte entfernt. Dieser Thread läuft normalerweise mit
niedrigster Priorität. Wenn das System also arbeitet (z.B
eine While-Schleife), dann wird kein Speicher freigegeben,
obwohl der gc Objekte erfaßt und markiert. Wenn das System
jetzt an die Speichergrenze stößt, dann wird leider nur der
gc aufgerufen und danach noch einmal der freie Speicher
geprüft. Da dieser aber nicht über den gc freigegeben wird,
ist immer noch zu wenig Speicher vorhanden und Java wirft
einen OOM-Error. Der Code den ich Fiete geschickt habe setzt
die Priorität des Finalizer-Threads auf Maximum, auf diese
Weise werden alle Objekte augenblicklich aus dem Speicher
entfernt, wenn der gc sie markiert hat. Dies hat nach meiner
Erfahrung nicht nur eine Verhinderung des obigen Errors zur
Folge sondern hat auch eine wesentlich bessere Performance
zur Folge.
Derethor
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ich habe meinen Ansatz ein wenig verfolgt und mittels thread sekündlich freeMemory, totalMemory und maxMemory angezeigt (alles in MB).
Maxheap hier default = ca 64MB, kann ja durch startparameter gesetzt werden...auslesen verfügbar erst ab java 1.4.!
Ich denke, so könnte man das abfangen...entweder routinemässig beim Anlegen einer neuen Region durch ParseCR oder wie hier gezeigt mit extra - Thread.
Ist totalHeap = maxHeap und freeMemory kleiner 5% (?) von maxHeap -> abbruch des Lesens + Fehlermeldung.
Wichtig: dass würde aber Umstieg auf Java JRE 1.4. als Mindestanforderung erzwingen! (1.3. hat kein maxHeap)
Fiete
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ich habe meinen Ansatz ein wenig verfolgt und mittels thread sekündlich freeMemory, totalMemory und maxMemory angezeigt (alles in MB).
Maxheap hier default = ca 64MB, kann ja durch startparameter gesetzt werden...auslesen verfügbar erst ab java 1.4.!
Ich denke, so könnte man das abfangen...entweder routinemässig beim Anlegen einer neuen Region durch ParseCR oder wie hier gezeigt mit extra - Thread.
Ist totalHeap = maxHeap und freeMemory kleiner 5% (?) von maxHeap -> abbruch des Lesens + Fehlermeldung.
Wichtig: dass würde aber Umstieg auf Java JRE 1.4. als Mindestanforderung erzwingen! (1.3. hat kein maxHeap)
Fiete
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sooo...ich habe die Finalizer-Prio auf thread.Max gesetzt, wie von Helge vorgeschlagen...
UND habe das Laden des CRs "sicher(er)" gemacht:
Unterschreitet freeMemory nach dem parsen einer Region einen festgelegten Wert (20K), wird der GC aufgerufen, 3 Sekunden (may change) gewartet und erneut geprüft. Wenn dann immer noch kritisch, wird das Laden abgebrochen, die GameData leer gemacht und ein Flag gesetzt, dass es einen Fehler gab.
Der führt dann im Client zur Ausgabe einer schönen Box.
So..jetzt das Problem. Dummerweise scheint die FinalizerPrioanpassung so effektiv zu sein, dass ich den Fehler nicht mehr reproduzieren kann, wie so schön früher, mit dem Laden des EWG-CRs ohne zusätzliche Einstellungen (also mit maxHeap = 65MB) - er lädt einfach - kein Fehler..tsss.
Daher meine Frage: bei welchen Vorgängen kommen bei euch die OutOfMemories?
Einen Kandidaten hab ich schon: Nach Passwortänderung im grossen CR konnte ich hier mal einen beobachten....
Ich möchte gezielt diese Vorgänge überwachen....
Gruss
Fiete
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Logged In: NO
Das geht so einfach leider nicht. Zum einen handelt es sich
dabei um einen Error und keine Exception, so das sie
normalerweise nicht gefangen werden sollte. Ist in diesem
Fall auch nicht sinnvoll, weil man damit nichts machen kann,
weil eben kein Speicher mehr zur Verfügung steht (eine
Anzeige per Dialog fällt somit z.B. aus).
Das die Meldung im Log steht liegt vermutlich daran, weil
alles, was nach System.err/System.out geschrieben wird im
log landet. Das wird automatisch von Java gemacht, wenn der
Fehler auftritt. Normalerweise stürzt eine Anwendung dabei
ab (genauer: der ausführende Thread stürzt ab). Es gibt
normalerweise keine vernünftige Möglichkeit dieses Problem
zu detektieren und darauf zu reagieren. Ich glaube, man kann
ihn nicht einmal per try() catch() fangen, da dabei eine
Variable zugewiesen werden soll, was wieder Speicher
verbrauchen würde, den man ja aber gar nicht zur Verfügung
hat. Ein OutOfMemoryError ist so ziemlich das böseste, was
einem passieren kann. Leider wird er von Java auch dann
geworfen, wenn die Vorraussetzung (kein Speicher mehr
verfügbar) gar nicht wirklich zutrifft. Das kann man
allerdings verhindern, indem man den Finalizer-Thread von
Java mit höchster Priorität laufen läßt (Ich mail Fiete mal
die entsprechenden Code-Zeilen, die dafür nötig sind).
Derethor
Logged In: YES
user_id=26454
Habe Zeilen erhalten.
magellan leitet system.err system.out in das log um...(client.java)
Zu den Zeilen von Derethor aka Helge frag ich ihn direkt noch....provided as is kann ich damit noch zu wenig
anfangen..-,))
In einem anderen Leben hatte ich mal versucht, den noch freien Speicher zu prüfen und wenn der zu gering wurde,
habe ich (damals) den garbage collector angeworfen, und wenn das nicht gereicht hat, mit Fehlermeldung
prophylaktisch abgebrochen....
FF
Logged In: YES
user_id=1283754
Ich habe ja auch nicht gesagt, dass es einfach wäre ;)
Also erstens: Doch, man kann auch OOMErrors abfangen.
Zweitens: Nur in der Theorie steht danach kein Speicher zur
Verfügung. Wenn man den Fehler weit genug oben abfängt, ist
in der Regel auch wieder Speicher freigeworden, oder?. Ich
hatte schon zahlreiche OOMErrors, aber selten ist Magellan
deswegen abgestürzt. Drittens: Wir brauchen ja nicht
unbedingt eine perfekte Fehlerbehandlung, es reichen erst
mal die typischen Fälle. Speicher wird vor allem gebraucht
beim Lesen und beim Schreiben von Reports. Dann noch
überall, wo User-Interface aufgebaut wird. Ersteres sollte
relativ leicht zu behandeln sein, Letzteres ist etwas
schwieriger. Noch zwei Beispiele aus meiner errors.txt:
Exception on Toolkit thread: java.lang.OutOfMemoryError:
Java heap space
java.lang.OutOfMemoryError: Java heap space
Exception in thread "AWT-EventQueue-0"
java.lang.OutOfMemoryError: Java heap space
Exception in thread "AWT-EventQueue-0"
java.lang.OutOfMemoryError: Java heap space
Zusatzfrage (für 2 Extrapunkte): Ist es möglich, der JVM vom
Programm aus mehr Speicher zuzuweisen? Vermutlich nicht.
Dann sollten wir zumindest (wieder?) eine
magellan.bat/magellan.sh zur Verfügung stellen, die java mit
mehr als dem Standard von 64MB aufruft.
Logged In: YES
user_id=26454
mit java 5 starte ich:
Zur Zusatzfrage:
java.exe -Xms400M -Xmx500M -jar magellan_act.jar
mit java 1_3 starte ich:
java.exe -Xms400MB -Xmx500MB -jar magellan_act.jar
Dass vorgehen ist auch in der Magellan FAQ empfohlen ;-))
Und meine grossen Reports bekomme ich sonst niemals geladen..;_)
FF
Logged In: NO
Ich habe nicht gesagt, das man den nicht abfangen kann,
allerdings SOLLTE man es nicht tun. Ein Error ist ein
schwerwiegendes Problem, das man in der Regel nicht mehr
behandeln kann. Magellan ist unter Umständen nicht
abgestürzt, aber der Thread, der gerade ausgeführt wurde
(Beim Ausführen eines Kommandos wird von der Oberfläche ein
Thread gestartet, der die eigentliche Methode aufruft damit
die Oberfläche nicht blockiert). Deshalb bleibt die
Oberfläche bestehen, aber der Thread (und alle Daten die in
seinen Kontext gehören, und da gehört auch der Error dazu)
sind dann weg.
Allerdings wirft Java, wie schon erwähnt auch einen OOM,
wenn dies eigentlich falsch ist. Dazu muß man wissen, das
Der gc NICHT für freien Speicher sorgt, sondern das er
Objekte als freizugeben markiert. Der Speicher gilt erst als
freigegeben, wenn der Finalizer-Thread diese markierten
Objekte entfernt. Dieser Thread läuft normalerweise mit
niedrigster Priorität. Wenn das System also arbeitet (z.B
eine While-Schleife), dann wird kein Speicher freigegeben,
obwohl der gc Objekte erfaßt und markiert. Wenn das System
jetzt an die Speichergrenze stößt, dann wird leider nur der
gc aufgerufen und danach noch einmal der freie Speicher
geprüft. Da dieser aber nicht über den gc freigegeben wird,
ist immer noch zu wenig Speicher vorhanden und Java wirft
einen OOM-Error. Der Code den ich Fiete geschickt habe setzt
die Priorität des Finalizer-Threads auf Maximum, auf diese
Weise werden alle Objekte augenblicklich aus dem Speicher
entfernt, wenn der gc sie markiert hat. Dies hat nach meiner
Erfahrung nicht nur eine Verhinderung des obigen Errors zur
Folge sondern hat auch eine wesentlich bessere Performance
zur Folge.
Derethor
Logged In: YES
user_id=26454
Originator: NO
Ich habe meinen Ansatz ein wenig verfolgt und mittels thread sekündlich freeMemory, totalMemory und maxMemory angezeigt (alles in MB).
Maxheap hier default = ca 64MB, kann ja durch startparameter gesetzt werden...auslesen verfügbar erst ab java 1.4.!
Normaler Vorgang beim Laden eines CR:
MW Free: 1, heap: 12, maxHeap: 65
MW Free: 4, heap: 12, maxHeap: 65
MW Free: 14, heap: 33, maxHeap: 65
Heap geht hoch....jetzt der EWG-CR (viel zu gross...ich weiss es vorher..;-))
...
MW Free: 4, heap: 65, maxHeap: 65
MW Free: 2, heap: 65, maxHeap: 65
MW Free: 1, heap: 65, maxHeap: 65
MW Free: 0, heap: 65, maxHeap: 65
MW Free: 0, heap: 65, maxHeap: 65
MW Free: 1, heap: 65, maxHeap: 65
MW Free: 0, heap: 65, maxHeap: 65
[5x...]
MW Free: 0, heap: 65, maxHeap: 65
Exception in thread "Thread-8" java.lang.OutOfMemoryError: Java heap space
MW Free: 0, heap: 65, maxHeap: 65
Ich denke, so könnte man das abfangen...entweder routinemässig beim Anlegen einer neuen Region durch ParseCR oder wie hier gezeigt mit extra - Thread.
Ist totalHeap = maxHeap und freeMemory kleiner 5% (?) von maxHeap -> abbruch des Lesens + Fehlermeldung.
Wichtig: dass würde aber Umstieg auf Java JRE 1.4. als Mindestanforderung erzwingen! (1.3. hat kein maxHeap)
Fiete
Logged In: YES
user_id=26454
Originator: NO
Ich habe meinen Ansatz ein wenig verfolgt und mittels thread sekündlich freeMemory, totalMemory und maxMemory angezeigt (alles in MB).
Maxheap hier default = ca 64MB, kann ja durch startparameter gesetzt werden...auslesen verfügbar erst ab java 1.4.!
Normaler Vorgang beim Laden eines CR:
MW Free: 1, heap: 12, maxHeap: 65
MW Free: 4, heap: 12, maxHeap: 65
MW Free: 14, heap: 33, maxHeap: 65
Heap geht hoch....jetzt der EWG-CR (viel zu gross...ich weiss es vorher..;-))
...
MW Free: 4, heap: 65, maxHeap: 65
MW Free: 2, heap: 65, maxHeap: 65
MW Free: 1, heap: 65, maxHeap: 65
MW Free: 0, heap: 65, maxHeap: 65
MW Free: 0, heap: 65, maxHeap: 65
MW Free: 1, heap: 65, maxHeap: 65
MW Free: 0, heap: 65, maxHeap: 65
[5x...]
MW Free: 0, heap: 65, maxHeap: 65
Exception in thread "Thread-8" java.lang.OutOfMemoryError: Java heap space
MW Free: 0, heap: 65, maxHeap: 65
Ich denke, so könnte man das abfangen...entweder routinemässig beim Anlegen einer neuen Region durch ParseCR oder wie hier gezeigt mit extra - Thread.
Ist totalHeap = maxHeap und freeMemory kleiner 5% (?) von maxHeap -> abbruch des Lesens + Fehlermeldung.
Wichtig: dass würde aber Umstieg auf Java JRE 1.4. als Mindestanforderung erzwingen! (1.3. hat kein maxHeap)
Fiete
Logged In: YES
user_id=26454
Originator: NO
Sooo...ich habe die Finalizer-Prio auf thread.Max gesetzt, wie von Helge vorgeschlagen...
UND habe das Laden des CRs "sicher(er)" gemacht:
Unterschreitet freeMemory nach dem parsen einer Region einen festgelegten Wert (20K), wird der GC aufgerufen, 3 Sekunden (may change) gewartet und erneut geprüft. Wenn dann immer noch kritisch, wird das Laden abgebrochen, die GameData leer gemacht und ein Flag gesetzt, dass es einen Fehler gab.
Der führt dann im Client zur Ausgabe einer schönen Box.
So..jetzt das Problem. Dummerweise scheint die FinalizerPrioanpassung so effektiv zu sein, dass ich den Fehler nicht mehr reproduzieren kann, wie so schön früher, mit dem Laden des EWG-CRs ohne zusätzliche Einstellungen (also mit maxHeap = 65MB) - er lädt einfach - kein Fehler..tsss.
Daher meine Frage: bei welchen Vorgängen kommen bei euch die OutOfMemories?
Einen Kandidaten hab ich schon: Nach Passwortänderung im grossen CR konnte ich hier mal einen beobachten....
Ich möchte gezielt diese Vorgänge überwachen....
Gruss
Fiete