Java'da bir istisna atmadan yığın izini dökmenin bir yolu var mı?


159

Java uygulamam için bir hata ayıklama aracı oluşturmayı düşünüyorum.

Bir yığın izlemesi elde etmenin mümkün olup olmadığını merak ediyorum, Exception.printStackTrace()ama aslında bir istisna atmadan?

Amacım, herhangi bir yöntemde, arayan kişinin kim olduğunu görmek için bir yığın dökmektir.

Yanıtlar:


84

Ayrıca Thread.getAllStackTraces()tüm iş parçacıkları için yığın izlerinin bir haritasını almaya çalışabilirsiniz .


250

Evet, sadece kullan

Thread.dumpStack()

44
... ama atmıyor.
Rob

5
Aslında soruyu ele alan cevap budur.
bruno

7
Çok basit ve zarif. Bu kabul edilen cevap olmalıydı.
deLock

11
Fwiw, bu yöntemin kaynağı: public static void dumpStack() { new Exception("Stack trace").printStackTrace(); }
JohnK

Bu, çıktıdan memnunsanız stderr, sorunun anlamı gibi görünen soruya en iyi cevaptır .
mike kemirgen

46

Yalnızca geçerli iş parçacığının izini istiyorsanız (Ram'in önerdiği gibi sistemdeki tüm iş parçacıkları yerine), şunları yapın:

Thread.currentThread ().getStackTrace ()

Arayanı bulmak için şunları yapın:

private String getCallingMethodName() {
    StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
    return callingFrame.getMethodName();
}

Ve bu yöntemi, arayan kişinin kim olduğunu bilmesi gereken yöntem içinden çağırın. Bununla birlikte, bir uyarı kelimesi: listedeki çağıran çerçevenin dizini JVM! Her şey, izlemenin oluşturulduğu noktaya gelmeden önce getStackTrace içinde kaç çağrı katmanı olduğuna bağlıdır. Daha sağlam bir çözüm, iz almak ve yinelemek için getCallingMethodName için çerçeve aramak olacaktır, daha sonra gerçek arayanı bulmak için iki adım daha ileri gidebilirsiniz.


2
Kendi başınıza yeni bir İstisna oluşturun ve dizin olarak [1] kullanın!
Daniel

3
Bu sorunun başlığı "istisnasız" diyor. Verilmiş, istisna oluşturmayı önermiş ancak atmamanızı öneririz, ancak yine de bunun sorunun ruhunda olmadığını düşünüyorum.
Tom Anderson

1
Tabiki öyle. İstisna oluşturmak, yığın izlemesi almanın en düşük düzey yoludur. Hatta Thread.currentThread (). GetStackTrace () bunu yapar, ancak benim yolum daha hızlı yapar :).
Daniel

@Daniel Başka bir husus daha var: Spock gibi birçok test çerçevesiyle, sadece bir istisna oluşturmak (atmadan), çerçeveyi almak için yeterli olacaktır: test daha sonra bir İstisnanın "meydana geldiğini" ve testin başarısızlıkla sonuçlanır.
mike rodent

@mikerodent: Emin misin? Spock bunu yapmak için ajanları kullanmak zorunda kalacaktı. Ama yine de, ben sadece sınıf çağırmak gerekiyordu çünkü ben bir yarar fonksiyonunda Reflection.getCallerClass (2) kullandım. İşlevi ve hat numarasını bu şekilde elde edemezsiniz, diye düşündü.
Daniel

37

Bunun gibi bir yığın izlemesi alabilirsiniz:

Throwable t = new Throwable();
t.printStackTrace();

Çerçeveye erişmek istiyorsanız, yığın çerçeve dizisi almak için t.getStackTrace () öğesini kullanabilirsiniz.

Hotspot derleyicisi bir şeyleri optimize etmekle meşgulse, bu yığın izinin (diğerleri gibi) bazı kareleri eksik olabileceğini unutmayın.


Bu yanıtı beğendim çünkü çıktıyı yönlendirme fırsatı sunuyor. Ben yerine t.printStackTracesahip t.printStackTrace(System.out).

4
Bir satırda:new Throwable().printStackTrace(System.out);

1
Bu kabul edilen cevap olmalı. Basit ve anlaşılır! Paylaştığınız için teşekkürler
Sam

2
ve java.util.Logger'a göndermek kolaydırlog.log(Level.SEVERE, "Failed to do something", new Throwable());
MitchBroadhead

13

Thread.dumpStack () yönteminin aslında bir istisna oluşturduğuna dikkat edin:

new Exception("Stack trace").printStackTrace();

12
Bir istisna yaratır, ancak atmaz.
MatrixFrog

6

Ayrıca JVM'ye çalışmakta olan bir Java işleminde Thread.getAllStackTraces () yöntemini yürütmek için işleme bir QUIT sinyali göndererek de sinyal gönderebilirsiniz.

Unix / Linux kullanımında:

kill -QUIT process_idBurada process_id, Java programınızın işlem numarasıdır.

Windows'ta uygulamada Ctrl-Break tuşuna basabilirsiniz, ancak bir konsol işlemi çalıştırmadığınız sürece bunu genellikle görmezsiniz.

JDK6, bilgisayarınızda çalışan herhangi bir JDK6 işleminden yığını görüntüleyen başka bir seçenek olan jstack komutunu tanıttı:

jstack [-l] <pid>

Bu seçenekler, bir üretim ortamında çalışan ve kolayca değiştirilemeyen uygulamalar için çok kullanışlıdır. Özellikle çalışma zamanı kilitlenmelerini veya performans sorunlarını teşhis etmek için kullanışlıdırlar.

http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/ http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html


6

Yakalama çıktısına ihtiyacınız varsa

StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();

6

Java 9, StackWalker , yığını yürümek için ve destekleyici sınıfları .

İşte Javadoc'tan birkaç parçacık:

walkYöntem, bir sıralı akışı açılır StackFramesŞu anki işlem için ve daha sonra yürüyüş verilen fonksiyonu uygular StackFrameakışı. Akış, yığın çerçeve öğelerini sıranın oluşturulduğu yürütme noktasını temsil eden en üst çerçeveden en alt çerçeveye doğru sıralar. StackFrameDere zaman yürüyüş yöntemi döner kapalıdır. Kapalı akışı yeniden kullanma girişiminde bulunulursa IllegalStateExceptionatılır.

...

  1. Geçerli iş parçacığının ilk 10 yığın karesini anlık olarak görüntülemek için,

    List<StackFrame> stack = StackWalker.getInstance().walk(s ->
     s.limit(10).collect(Collectors.toList()));

0

HPROF Java Profili Oluşturucu

Bunu kodda yapmak zorunda bile değilsiniz. Java HPROF'u işleminize ekleyebilir ve herhangi bir noktada yığın dökümü, çalışan iş parçacıkları vb. Çıktı almak için Control- \ tuşuna basabilirsiniz. . . uygulama kodunuzu değiştirmeden. Bu biraz modası geçmiş, Java 6 GUI jconsole ile geliyor, ancak yine de HPROF'un çok yararlı olduğunu düşünüyorum.


0

Rob Di Marco tarafından cevap size çıkışa mutlu ise iyi gereğidir stderr.

StringNormal bir ize göre yeni satırlarla a yakalamak istiyorsanız , bunu yapabilirsiniz:

Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.