Ich habe Instanzen unseres Java-Codes abfangen lassen NullPointerException
, aber wenn ich versuche, die StackTrace zu protokollieren (die im Grunde genommen aufruft Throwable.printStackTrace()
), bekomme ich nur:
java.lang.NullPointerException
Ist noch jemand darauf gestoßen? Ich habe versucht, nach "Java Null Pointer Leerer Stack Trace" zu googeln, bin aber auf so etwas nicht gestoßen.
java
nullpointerexception
Edward Shtern
quelle
quelle
-XX:-OmitStackTraceInFastThrow
im Dup: stackoverflow.com/questions/4659151/…Antworten:
Sie verwenden wahrscheinlich die HotSpot-JVM (ursprünglich von Sun Microsystems, später von Oracle gekauft, Teil des OpenJDK), die viele Optimierungen durchführt. Um die Stack-Traces zurückzugewinnen, müssen Sie die Option
-XX:-OmitStackTraceInFastThrow
an die JVM übergeben.Die Optimierung besteht darin, dass beim erstmaligen Auftreten einer Ausnahme (normalerweise einer NullPointerException) die vollständige Stapelverfolgung gedruckt wird und die JVM die Stapelverfolgung (oder möglicherweise nur den Speicherort des Codes) speichert. Wenn diese Ausnahme häufig genug auftritt, wird die Stapelverfolgung nicht mehr gedruckt, um eine bessere Leistung zu erzielen und das Protokoll nicht mit identischen Stapelverfolgungen zu überfluten.
Um zu sehen, wie dies in der HotSpot-JVM implementiert ist , nehmen Sie eine Kopie davon und suchen Sie nach der globalen Variablen
OmitStackTraceInFastThrow
. Das letzte Mal, als ich mir den Code angesehen habe (2019), war er in der Datei graphKit.cpp .quelle
-XX:-OmitStackTraceInFastThrow
Flag zu akzeptieren . Ich muss noch bestätigen, ob ich aus diesem Grund auch keine Stack-Traces gedruckt habe (z. B. mite.printStackTrace
), aber es scheint sehr wahrscheinlich. Ich habe die Antwort erweitert, um diese Entdeckung widerzuspiegeln.Wie Sie in einem Kommentar erwähnt haben, verwenden Sie log4j. Ich entdeckte (versehentlich) einen Ort, an dem ich geschrieben hatte
anstelle des typischen
durch Faulheit oder vielleicht einfach nicht darüber nachdenken. Der unglückliche Teil davon ist, dass es sich nicht so verhält, wie Sie es erwarten. Die Logger-API verwendet Object als erstes Argument, nicht als Zeichenfolge, und ruft dann für das Argument toString () auf. Anstatt die schöne hübsche Stapelverfolgung zu erhalten, wird nur der toString ausgedruckt - was im Fall von NPE ziemlich nutzlos ist.
Vielleicht erleben Sie das gerade?
quelle
Wir haben das gleiche Verhalten in der Vergangenheit gesehen. Es stellte sich heraus, dass aus irgendeinem verrückten Grund, wenn eine NullPointerException mehrmals an derselben Stelle im Code auftrat, nach einer Weile die Verwendung
Log.error(String, Throwable)
der vollständigen Stapelspuren eingestellt wurde.Versuchen Sie, in Ihrem Protokoll weiter zurückzublicken. Sie können den Täter finden.
BEARBEITEN: Dieser Fehler klingt relevant, wurde aber vor so langer Zeit behoben, dass er wahrscheinlich nicht die Ursache ist.
quelle
-XX:-OmitStackTraceInFastThrow
von Joshua vorgeschlagene JVM-Flagge ausprobiert ? Siehe auch stackoverflow.com/a/2070568/6198 .Hier ist eine Erklärung: Hotspot hat dazu geführt, dass Ausnahmen ihre Stapelspuren in der Produktion verloren haben - und das Update
Ich habe es unter Mac OS X getestet
64-Bit-Server-VM von Java HotSpot (TM) (Build 20.1-b02-383, gemischter Modus)
Für dieses spezifische Codefragment scheinen 12288 Iterationen (+ Häufigkeit?) Die Grenze zu sein, an der JVM beschlossen hat, eine vorab zugewiesene Ausnahme zu verwenden ...
quelle
exception.toString
gibt Ihnen nicht die StackTrace, sondern gibt nur zurückVerwenden Sie
exception.printStackTrace
stattdessen, um StackTrace auszugeben.quelle
getStackTrace()
, sicherzustellen, dass das Problem nicht bei Ihrem Logger liegt?Alternativer Vorschlag - Wenn Sie Eclipse verwenden, können Sie einen Haltepunkt für NullPointerException selbst festlegen (gehen Sie in der Debug-Perspektive zur Registerkarte "Haltepunkte" und klicken Sie auf das kleine Symbol mit einem!).
Aktivieren Sie sowohl die Optionen "Abgefangen" als auch "Nicht erfasst". Wenn Sie jetzt die NPE auslösen, erhalten Sie sofort einen Haltepunkt. Anschließend können Sie durchgehen und sehen, wie genau damit umgegangen wird und warum Sie keine Stapelverfolgung erhalten.
quelle
toString()
Gibt nur den Ausnahmenamen und die optionale Nachricht zurück. Ich würde vorschlagen anzurufenum die Nachricht zu sichern, oder wenn Sie die blutigen Details benötigen:
quelle
(Ihre Frage ist immer noch unklar, ob Ihr Code aufgerufen wird
printStackTrace()
oder ob dies von einem Protokollierungshandler durchgeführt wird.)Hier sind einige mögliche Erklärungen darüber, was passieren könnte:
Der verwendete Logger / Handler wurde so konfiguriert, dass nur die Nachrichtenzeichenfolge der Ausnahme ausgegeben wird, keine vollständige Stapelverfolgung.
Ihre Anwendung (oder eine Bibliothek eines Drittanbieters) protokolliert die Ausnahme mithilfe
LOG.error(ex);
der 2-Argument-Form (zum Beispiel) der log4j-Logger-Methode.Die Nachricht kommt von einem anderen Ort, als Sie denken. Zum Beispiel handelt es sich tatsächlich um eine Bibliotheksmethode eines Drittanbieters oder um zufällige Dinge, die von früheren Debugversuchen übrig geblieben sind.
Die Ausnahme, die protokolliert wird, hat einige Methoden überladen, um die Stapelverfolgung zu verdecken. In diesem Fall handelt es sich bei der Ausnahme nicht um eine echte NullPointerException, sondern um einen benutzerdefinierten Subtyp von NPE oder sogar um eine nicht verbundene Ausnahme.
Ich denke, dass die letztmögliche Erklärung ziemlich unwahrscheinlich ist, aber die Leute denken zumindest darüber nach, so etwas zu tun, um Reverse Engineering zu "verhindern". Natürlich gelingt es nur wirklich, ehrlichen Entwicklern das Leben schwer zu machen.
quelle
Wenn Sie AspectJ in Ihrem Projekt verwenden, kann es vorkommen, dass ein Aspekt seinen Teil der Stapelverfolgung verbirgt. Zum Beispiel hatte ich heute:
Diese Stapelverfolgung wurde gedruckt, als der Test über Mavens todsicheres Feuer ausgeführt wurde.
Andererseits wurde beim Ausführen des Tests in IntelliJ eine andere Stapelverfolgung gedruckt:
quelle
Dadurch wird die Ausnahme ausgegeben. Verwenden Sie sie nur zum Debuggen. Sie sollten Ihre Ausnahmen besser behandeln.
quelle