Christian: Frage zu Vector

Hi!

Ich habe einen Vector, den ich bei einer Berechung fülle. Wenn aber sehr viele Ergebnisse kommen, kriege ich irgendwann einen "java.lang.OutOfMemoryError".

Kann ich den Fehler irgendwie abfangen? Ich würde das Programm gerne so ändern, daß die Ergebnisse auf die Festplatte geschrieben werden, falls nicht genug Speicher vorhanden ist.

Mit einem Try, Catch Block kann ich den Fehler leider nicht abfangen...

  1. Hallo Christian,

    Nein den kannst Du nicht abfangen. Wenn die VM über keinen freien Speicher mehr verfügt, kann sie auch keine Ausnahmenverarbeitung mehr machen. Dazu müsste sie ja erst irgend etwas willkürlich freigeben.
    Du kannst aber vorher abfragen, wie viel Speicher Dir zur Verfügung steht, bzw wie viel noch frei ist:

    Siehe freeMemory() und maxMemory() http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html

    Am besten versuchst Du aber erst gar nicht, möglichst viel Speicher zu nutzen, sondern schreibst die Ergebnisse häufig genug auf die Platte.
    Eine Möglichkeit wäre auch noch mit http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ref/SoftReference.html zu arbeiten. Objekte, die so referenziert werden, werden vom GC gelöscht, wenn Speicher benötigt wird. Du kannst sie dann in der finalize() Methode vorher speichern.
    Der Nachteil dabei ist, dass Du nicht weist, in welcher Reihenfolge der GC aufräumt. Aber er wird es genau dann tun, wenn der freie Speicher knapp wird.

    Grüße

    Daniel

    1. Hallo,

      Nein den kannst Du nicht abfangen. Wenn die VM über keinen freien Speicher mehr verfügt, kann sie auch keine Ausnahmenverarbeitung mehr machen. Dazu müsste sie ja erst irgend etwas willkürlich freigeben.

      Doch, man kann das schon abfangen. Man sollte danach aber nicht mehr
      sehr viele Objekte auf dem Heap anlegen. :-)

      Du kannst aber vorher abfragen, wie viel Speicher Dir zur Verfügung steht, bzw wie viel noch frei ist:

      Siehe freeMemory() und maxMemory() http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html

      Zumindest freeMemory() gibt oft aber auch eher Fantasie-Werte zurück.

      Am besten versuchst Du aber erst gar nicht, möglichst viel Speicher zu nutzen, sondern schreibst die Ergebnisse häufig genug auf die Platte.

      Jop.

      Gruß
      Slyh

      1. Hallo Slyh,

        Ich habe das nicht ausprobiert, sondern nur daraus geschlossen, dass das ein VirtualMemoryError ist, und die Doku dazu sagt: "Thrown to indicate that the Java Virtual Machine is broken or has run out of resources necessary for it to continue operating."
        Was kann man denn überhaupt noch machen, nachdem man diesen Fehler abgefangen hat?

        Zumindest freeMemory() gibt oft aber auch eher Fantasie-Werte zurück.

        Der Speicher, den die VM benutzen kann ist ja nicht der gesamte Speicher.
        Die Speicherverwaltung der VM ist aber so komplex und so stark Implementierungsabhängig, dass einem diese Methode wohl nichts bringt.
        (Außer um schöne Auslastungsbalken zu erzeugen oder ähnliches)

        Grüße

        Daniel

        1. Hi ihr beiden,

          Ich habe das nicht ausprobiert, sondern nur daraus geschlossen, dass das ein VirtualMemoryError ist, und die Doku dazu sagt: "Thrown to indicate that the Java Virtual Machine is broken or has run out of resources necessary for it to continue operating."
          Was kann man denn überhaupt noch machen, nachdem man diesen Fehler abgefangen hat?

          Nichts, da die Specification auch sagt:
          "11.5.2 Virtual Machine Errors
          The Java virtual machine throws an object that is an instance of a subclass of the class VirtualMachineError when an internal error or resource limitation prevents it from implementing the semantics of the Java programming language. See The Java Virtual Machine Specification Second Edition for the definitive discussion of these errors."

          Das interpretiere ich so, dass nach dem Wurf des java.lang.OutOfMemoryErrors (also im scope des catch-Blocks) das VM-Verhalten nicht mehr deterministisch ist, was dann effektiv wohl "spekulativem" Programmieren gleich käme.

          Viele Grüße,
          Martin Jung

          1. Hallo Martin,

            The Java virtual machine throws an object that is an instance of a subclass of the class VirtualMachineError when an internal error or resource limitation prevents it from implementing the semantics of the Java programming language. See The Java Virtual Machine Specification Second Edition for the definitive discussion of these errors."

            Ja, was da steht, weiß ich auch. Aber tatsächlich scheint nur die Instanzierung des Objekts fehl zu schlagen und ansonsten kann man ganz normal weiter arbeiten.

            public static void main(String[] argv) {
                    int i = 0;
                    StringBuffer string = new StringBuffer();
                    try {

            while(true) {
                            i++;
                            string.append("text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text");
                        }
                    }
                    catch(OutOfMemoryError e) {
                        System.out.println(i);
                    }
                }

            Das Funktioniert zum Beispiel ganz ausgezeichnet. Man kann hier natürlich nicht besonders viel machen, ohne gleich die nächste Ausnahme zu erzeugen, aber die VM scheint da sonst keine weiteren Probleme zu haben, auch wenn die Spezifikation anderes erwarten lässt.

            Grüße

            Daniel

            1. Hi Daniel,

              Ja, was da steht, weiß ich auch.

              war nicht belehrend gemeint, sondern als Kontextinformation für Mitleser (Archiv ...).

              Aber tatsächlich scheint nur die Instanzierung des Objekts fehl zu schlagen und ansonsten kann man ganz normal weiter arbeiten.

              Das meinte ich ja: Man _kann_ evtl. ganz normal weiterarbeiten, dies ist aber dann _bereits_ im Sinne der Spezifikation (im Gegensatz zu einem Bug in einer VM-Implementierung) nicht mehr garantiert. Derartigen Code betrachte ich daher als fehlerhafte Implementierung.

              Viele Grüße,
              Martin Jung

              1. Hallo Martin Jung,

                Ja, was da steht, weiß ich auch.
                war nicht belehrend gemeint, sondern als Kontextinformation für Mitleser (Archiv ...).

                Ja, ich wollte auch nur klarstellen, dass mich das tatsächliche Verhalten interessiert hat. Ist etwas schroff ausgefallen.

                Das meinte ich ja: Man _kann_ evtl. ganz normal weiterarbeiten, dies ist aber dann _bereits_ im Sinne der Spezifikation (im Gegensatz zu einem Bug in einer VM-Implementierung) nicht mehr garantiert. Derartigen Code betrachte ich daher als fehlerhafte Implementierung.

                All exceptions in the Java programming language are precise: when the transfer of control takes place, all effects of the statements executed and expressions evaluated before the point from which the exception is thrown must appear to have taken place. No expressions, statements, or parts thereof that occur after the point from which the exception is thrown may appear to have been evaluated. If optimized code has speculatively executed some of the expressions or statements which follow the point at which the exception occurs, such code must be prepared to hide this speculative execution from the user-visible state of the program.
                (Java VM Spec 2.16.2 Handling an Exception)

                Nach eine Ausnahme muss also _immer_ der Zustand hergestellt sein, der vor der Ausnahme herrschte. Somit ist das Verhalten der VM auch von der Spezifikation garantiert.
                Mit dem von Dir zitierten Satz ist folglich wohl eher gemeint, dass die VM die eine Anweisung nicht korrekt umsetzen kann, aber sehr wohl korrekt weiterarbeiten.
                Normalerweise ist es natürlich kein besonders guter Stil so eine Ausnahme abzufangen, aber für einen Browser könnte es z.B. durchaus interessant sein, so eine Absturz durch ein Applet zu verhindern.

                Grüße

                Daniel

                1. Hi Daniel,

                  (Java VM Spec 2.16.2 Handling an Exception)

                  Nach eine Ausnahme muss also _immer_ der Zustand hergestellt sein, der vor der Ausnahme herrschte. Somit ist das Verhalten der VM auch von der Spezifikation garantiert.

                  Hmmmm, wenn meine Interpretation dieses Abschnitts korrekt ist, entgegne ich zurecht:
                   Exception instanceof Error == false

                  Mit dem von Dir zitierten Satz ist folglich wohl eher gemeint, dass die VM die eine Anweisung nicht korrekt umsetzen kann, aber sehr wohl korrekt weiterarbeiten.

                  Das geht ja leider nicht genau hervor, aber "...it from implementing the semantics of the Java programming language" klingt nach einem weiteren Kontext als der Catch Block.

                  Normalerweise ist es natürlich kein besonders guter Stil so eine Ausnahme abzufangen, aber für einen Browser könnte es z.B. durchaus interessant sein, so eine Absturz durch ein Applet zu verhindern.

                  Habe keine wirkliche praktische Erfahrung in Applet-Programmierung, würde aber im Zweifel ähnlich handeln.

                  Viele Grüße,
                  Martin Jung

                  1. Hallo Martin Jung,

                    Exception instanceof Error == false

                    Ja das stimmt natürlich. Aber hier geht es nicht um Exception im Sinne von "Instanz einer Exception-Klasse" sondern im um alles, was irgendwie geworfen werden kann.
                    Zitat aus der VM Spezifikation Kapitel "Exceptions":
                    Every exception is represented by an instance of the class Throwable or one of its subclasses;

                    Noch ein Link auf die Spec, da die nicht so einfach zu finden ist, wenn man nicht weiß, wo man suchen muss: http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html

                    Grüße

                    Daniel

                    1. Hi Daniel,

                      Ja das stimmt natürlich. Aber hier geht es nicht um Exception im Sinne von "Instanz einer Exception-Klasse" sondern im um alles, was irgendwie geworfen werden kann.
                      Zitat aus der VM Spezifikation Kapitel "Exceptions":
                      Every exception is represented by an instance of the class Throwable or one of its subclasses;

                      Dich zitierend: Ja das stimmt natürlich ;-)

                      Abgesehen davon, grundsätzlich sind wir bzgl. des Programmierstils ja ähnlicher Meinung.
                      In diesem Sinne: Bis zur nächsten Diskussion.

                      Viele Grüße,
                      Martin Jung

  2. Hallo,

    Ich habe einen Vector, den ich bei einer Berechung fülle. Wenn aber sehr viele Ergebnisse kommen, kriege ich irgendwann einen "java.lang.OutOfMemoryError".

    Guck dir mal den Programmparameter -Xmx von "java.exe" an.
    (Übersicht über die non-standard Paramter: "java -X").

    Kann ich den Fehler irgendwie abfangen? Ich würde das Programm gerne so ändern, daß die Ergebnisse auf die Festplatte geschrieben werden, falls nicht genug Speicher vorhanden ist.

    Du wirst nicht mehr auf die Daten zugreifen können, nachdem die
    Exception geworfen wurde.

    Mit einem Try, Catch Block kann ich den Fehler leider nicht abfangen...

    Doch, kannst du. (Hab das gerade ausprobiert. Es geht. Mindestens
    seit JDK 1.3. Davor weiß ich nicht.)

    Gruß
    Slyh