java - thread - Was ist ein Stack-Trace und wie kann ich ihn zum Debuggen von Anwendungsfehlern verwenden?




stacktrace c# (5)

Die anderen Beiträge beschreiben, was ein Stack-Trace ist, aber es kann immer noch schwierig sein, damit zu arbeiten.

Wenn Sie eine Stack-Ablaufverfolgung erhalten und die Ursache der Ausnahme verfolgen möchten, sollten Sie die Java-Stack-Trace-Konsole in Eclipse verwenden . Wenn Sie eine andere IDE verwenden, gibt es möglicherweise eine ähnliche Funktion, aber diese Antwort bezieht sich auf Eclipse.

Stellen Sie zunächst sicher, dass alle Ihre Java-Quellen in einem Eclipse-Projekt verfügbar sind.

Klicken Sie dann in der Java- Perspektive auf die Registerkarte Konsole (normalerweise unten). Wenn die Konsolenansicht nicht sichtbar ist, wechseln Sie zur Menüoption Fenster -> Ansicht anzeigen und wählen Sie Konsole .

Klicken Sie dann im Konsolenfenster auf den folgenden Button (rechts)

und wählen Sie Java Stack Trace Console aus der Dropdown-Liste.

Fügen Sie Ihren Stack-Trace in die Konsole ein. Es wird dann eine Liste von Links in Ihren Quellcode und anderen verfügbaren Quellcode zur Verfügung stellen.

Dies können Sie sehen (Bild aus der Eclipse-Dokumentation):

Der zuletzt durchgeführte Methodenaufruf ist der Anfang des Stapels, dh die oberste Zeile (ohne den Nachrichtentext). Den Stapel hinunter gehen geht zurück in der Zeit. Die zweite Zeile ist die Methode, die die erste Zeile usw. aufruft.

Wenn Sie Open-Source-Software verwenden, müssen Sie möglicherweise die Quellen herunterladen und an Ihr Projekt anhängen, wenn Sie dies untersuchen möchten. Laden Sie die Quell-Jars herunter, öffnen Sie in Ihrem Projekt den Ordner Referenced Libraries , um Ihr jar für Ihr Open-Source-Modul (das mit den Klassendateien) zu finden, klicken Sie mit der rechten Maustaste, wählen Sie Eigenschaften und hängen Sie das Quelljar an.

Manchmal, wenn ich meine Anwendung starte, gibt es einen Fehler, der wie folgt aussieht:

Exception in thread "main" java.lang.NullPointerException
        at com.example.myproject.Book.getTitle(Book.java:16)
        at com.example.myproject.Author.getBookTitles(Author.java:25)
        at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Die Leute haben dies als "Stack-Trace" bezeichnet. Was ist ein Stack-Trace? Was kann ich über den Fehler in meinem Programm wissen?

Über diese Frage - ziemlich oft sehe ich eine Frage, wo ein unerfahrener Programmierer "einen Fehler bekommt", und sie fügen einfach ihren Stack-Trace und irgendeinen zufälligen Code-Block ein, ohne zu verstehen, was der Stack-Trace ist oder wie er ihn benutzen kann. Diese Frage dient als Referenz für Anfänger-Programmierer, die Hilfe benötigen, um den Wert eines Stack-Trace zu verstehen.


Es gibt eine weitere Stacktrace-Funktion, die von Throwable family angeboten wird - die Möglichkeit, Stack-Trace-Informationen zu manipulieren .

Standardverhalten:

package test.stack.trace;

public class SomeClass {

    public void methodA() {
        methodB();
    }

    public void methodB() {
        methodC();
    }

    public void methodC() {
        throw new RuntimeException();
    }

    public static void main(String[] args) {
        new SomeClass().methodA();
    }
}

Stapelverfolgung:

Exception in thread "main" java.lang.RuntimeException
    at test.stack.trace.SomeClass.methodC(SomeClass.java:18)
    at test.stack.trace.SomeClass.methodB(SomeClass.java:13)
    at test.stack.trace.SomeClass.methodA(SomeClass.java:9)
    at test.stack.trace.SomeClass.main(SomeClass.java:27)

Manipulierte Stapelverfolgung:

package test.stack.trace;

public class SomeClass {

    ...

    public void methodC() {
        RuntimeException e = new RuntimeException();
        e.setStackTrace(new StackTraceElement[]{
                new StackTraceElement("OtherClass", "methodX", "String.java", 99),
                new StackTraceElement("OtherClass", "methodY", "String.java", 55)
        });
        throw e;
    }

    public static void main(String[] args) {
        new SomeClass().methodA();
    }
}

Stapelverfolgung:

Exception in thread "main" java.lang.RuntimeException
    at OtherClass.methodX(String.java:99)
    at OtherClass.methodY(String.java:55)

Um das hinzuzufügen, was Rob erwähnt hat. Wenn Sie in Ihrer Anwendung Breakpoints setzen, können Sie den Stack Schritt für Schritt bearbeiten. Dies ermöglicht dem Entwickler, den Debugger zu verwenden, um zu sehen, an welchem ​​Punkt die Methode etwas unternimmt, das nicht vorhergesehen wurde.

Da Rob die NullPointerException (NPE) verwendet hat, um etwas NullPointerException zu veranschaulichen, können wir helfen, dieses Problem auf folgende Weise zu NullPointerException :

Wenn wir eine Methode haben, die Parameter wie void (String firstName) : void (String firstName)

In unserem Code möchten wir auswerten, dass firstName einen Wert enthält, wir würden das folgendermaßen machen: if(firstName == null || firstName.equals("")) return;

Das obige verhindert, dass firstName als unsicherer Parameter verwendet wird. Indem wir vor der Verarbeitung Null-Checks durchführen, können wir sicherstellen, dass unser Code ordnungsgemäß ausgeführt wird. Um ein Beispiel zu erweitern, das ein Objekt mit Methoden verwendet, können wir hier nachsehen:

if(dog == null || dog.firstName == null) return;

Das obige ist die richtige Reihenfolge, um nach Nullen zu suchen, wir beginnen mit dem Basisobjekt, dem Hund in diesem Fall, und beginnen dann, den Baum der Möglichkeiten hinunterzugehen, um sicherzustellen, dass alles gültig ist, bevor es verarbeitet wird. Wenn die Reihenfolge umgekehrt würde, könnte möglicherweise eine NPE ausgelöst werden und unser Programm würde abstürzen.


Um den anderen Beispielen hinzuzufügen, gibt es innere (verschachtelte) Klassen , die mit dem $ -Zeichen erscheinen. Beispielsweise:

public class Test {

    private static void privateMethod() {
        throw new RuntimeException();
    }

    public static void main(String[] args) throws Exception {
        Runnable runnable = new Runnable() {
            @Override public void run() {
                privateMethod();
            }
        };
        runnable.run();
    }
}

Wird in diesem Stack-Trace resultieren:

Exception in thread "main" java.lang.RuntimeException
        at Test.privateMethod(Test.java:4)
        at Test.access$000(Test.java:1)
        at Test$1.run(Test.java:10)
        at Test.main(Test.java:13)

Um den Namen zu verstehen : Eine Stack-Trace ist eine Liste von Exceptions (oder Sie können eine Liste von "Cause by" sagen), von der Oberfläche Exception (zB Service Layer Exception) bis zum tiefsten (zB Database Exception). Genau wie der Grund, den wir es "Stack" nennen, weil Stack First in Last Out (FILO) ist, war die tiefste Ausnahme am Anfang, dann wurde eine Kette von Ausnahmen erzeugt eine Reihe von Konsequenzen, die Oberfläche Exception war die letzte Eines ist in der Zeit passiert, aber wir sehen es an erster Stelle.

Schlüssel 1 : Eine knifflige und wichtige Sache, die hier verstanden werden muss, ist: Die tiefste Ursache ist möglicherweise nicht die "Ursache", denn wenn Sie "schlechten Code" schreiben, kann dies zu einer Ausnahme führen, die tiefer liegt als die Ebene. Zum Beispiel kann eine fehlerhafte SQL-Abfrage dazu führen, dass die SQLServerException-Verbindung im Bottem zurückgesetzt wird, anstatt im syndax-Fehler, der gerade in der Mitte des Stacks liegt.

-> Suchen Sie die Ursache in der Mitte ist Ihre Aufgabe.

Schlüssel 2 : Eine weitere knifflige, aber wichtige Sache ist in jedem "Cause by" Block, die erste Linie war die tiefste Schicht und der erste Platz für diesen Block. Zum Beispiel,

Exception in thread "main" java.lang.NullPointerException
        at com.example.myproject.Book.getTitle(Book.java:16)
           at com.example.myproject.Author.getBookTitles(Author.java:25)
               at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Book.java:16 wurde von Auther.java:25 aufgerufen, welches von Bootstrap.java:14 aufgerufen wurde, Book.java:16 war die Ursache. Hier fügen Sie ein Diagramm hinzu, sortieren Sie den Trace-Stack in chronologischer Reihenfolge.





stack-trace