2016-05-29 6 views
2

Ich arbeite an einer einfachen Anwendung und jetzt bin ich nicht ganz sicher, wie mit Fehlern umzugehen ist, die während der Ausführung der Anwendung aufgetreten sind. Ich mache mir besonders Sorgen um OutOfMemoryError. Beispiel:Abnormale Beendigung im Catch-Block?

try{ 
     while(true){ 
      //do some job 
     } 
    } catch (Exception e){ 
     System.out.println("Exception occured"); 
    } catch (Throwable t){ 
     //log entry of abnormal termination 
     System.exit(1); 
    } finally { 
     //Terminate application normally 
    } 

Ist es ein richtiger Weg, um mit einer solchen Situation umzugehen? Ich meine, zu versuchen, Anwendung normalerweise zu beenden, blockieren Sie schließlich und töten Sie einfach JVM in catch(Throwable t).

Das Problem ist finally wird nie ausgeführt werden, wenn zum Beispiel OutOfMemoryError geworfen wurde.

Antwort

3

Ich glaube nicht, dass auch gebraucht wird, wenn Sie auf OutOfMemoryException Ihre JVM töten wollen, können Sie einige JVM-Flags sind:

-XX:OnOutOfMemoryError="kill -9 %p" 

es möglich sein kann etwas Speicher freizugeben, wenn OutOfMemoryException schlagen je was Sie tun, und es ist wahrscheinlich besser, explizit zu versuchen und fangen OutOfMemoryException statt Throwable zu fangen, die alles enthält, was geworfen werden kann.

+0

Nun, die Sache ist, ich möchte einen Protokolleintrag erstellen. Das ist der Hauptgrund, warum ich 'Throwable' erwische. – Alupkers

+0

Vielleicht lohnt sich, wenn Throwable instanceof OutOfMemoryException es abbricht, andernfalls loggen Sie es einfach ein. –

1

Wenn es sich um eine Single-Thread-Anwendung handelt, können Sie einfach das OOM protokollieren und die VM normal beenden lassen, und System.exit() nicht aufrufen. Wenn es sich um eine Multithread-Anwendung handelt, müssen Sie eine Richtlinie zum Herunterfahren haben. In jedem Szenario liegt es an Ihnen, welche Ressourcen und wie Sie beim Herunterfahren Ihrer Anwendung behandelt werden sollten. Sie machen sich Sorgen, dass Sie nach System.exit() endlich nicht mehr aufrufen, wenn Sie mehr Threads haben, werden sie getötet und Sie haben keine Kontrolle wann, sie hätten auch keine Chance für eine Finalisierung. Wenn Sie Ihre App ordnungsgemäß herunterfahren möchten, müssen Sie sie so programmieren, dass sie über die entsprechende Logik verfügt.

+0

Werden nicht alle Ressourcen zurückgerufen, wenn wir 'System.exit (1)' aufrufen? – Alupkers

+1

Sie sind in einem Bereich, der für OS und JVM möglich ist - aber es kann Ausnahmen geben, z. Anwendungen, die nativen Code verwenden. Aber es ist nicht der Punkt meiner Antwort, dass einige native Ressourcen nicht zu OS zurückkehren, aber wenn Ihre Threads etwas Transaktionales tun - z.Schreiben Sie einige "atomare" Datenblöcke in die Datei auf der Festplatte. Wenn Sie die VM dann beenden, besteht die große Wahrscheinlichkeit, dass sich Ihre Datei in einem inkonsistenten Zustand befindet, da sich dort einige Datenblöcke befinden. Es gibt viele Szenarien, in denen das Beenden der VM zu einem inkonsistenten Zustand Ihrer Anwendung führen könnte. –

1

Wenn Sie für eine Ausnahme System.exit(...) in einem catch Block aufrufen, wird ein finally Block nicht ausgeführt, wenn die Ausnahme abgefangen wird.

Angenommen, das ist was Sie wollen ... dann haben Sie Ihre Ausnahmebehandlung korrekt codiert.

Ist das der "richtige" Weg, damit umzugehen? Nun, wenn dies das ist, was Sie wollen (d. H. Wenn Sie wollen irgendwelche Error Ausnahmen, um die normale Terminierungslogik zu überspringen) dann ist es richtig. Aber letztendlich müssen Sie selbst entscheiden.

Having said that, wenn Sie befürchten, dass Ihre Anwendung wird die Kündigung nicht in der Lage sein, durchzuführen, da es nicht genügend Arbeitsspeicher ist, dann sind Sie so etwas tun könnte:

try { 
    int[] reserved = new int[1,000,000]; 
    while(true){ 
     //do some job 
    } 
} catch (Exception e){ 
    System.out.println("Exception occured"); 
} catch (Throwable t){ 
    //log entry of abnormal termination 
} 
// Terminate application normally << HERE 

Wenn die JVM wirft OOME, wenn Sie den "HERE" -Punkt erreichen, wird es 8 MB wiederverwendbaren Müll im Heap geben. Wenn der Beendigungscode den Heap (wieder) füllt, wird der GC den Müll zurückfordern und es sollte genug Platz sein, um die Beendigung abzuschließen.

+0

Was meinst du genug Platz, um die Beendigung abzuschließen? Benötigt es etwas Heap-Speicherplatz? – Alupkers

+0

@ Alupkers - Was ich sage ist, dass Ihre "Anwendung Code beenden" möglicherweise einige Heap-Speicherplatz benötigen. Wenn dies nicht der Fall ist, gibt es kein Problem und keinen Platz zu reservieren. –

Verwandte Themen