Yığın izleme nedir ve uygulama hatalarımda hata ayıklamak için nasıl kullanabilirim?


644

Bazen uygulamamı çalıştırdığımda bana şöyle bir hata veriyor:

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)

İnsanlar buna "yığın izi" adını verdiler. Yığın izi nedir? Programımda meydana gelen hata hakkında bana ne söyleyebilir?


Bu soru hakkında - sık sık acemi bir programcının "bir hata alıyorum" olduğu bir soru geldiğini görüyorum ve yığın izinin ne olduğunu veya nasıl kullanabileceklerini anlamadan yığın izlerini ve rastgele bir kod bloğunu yapıştırıyorlar. Bu soru, yığın izlemenin değerini anlama konusunda yardıma ihtiyaç duyan acemi programcılar için bir referans olarak tasarlanmıştır.


25
Ayrıca, bir yığın izleme satırı dosya adı ve bir satır numarası içermiyorsa, bu satırın sınıfı hata ayıklama bilgileriyle derlenmemiştir.
Thorbjørn Ravn Andersen

Yanıtlar:


589

Basit bir ifadeyle, yığın izlemesi , uygulamanın bir İstisna atıldığında ortasında olduğu yöntem çağrılarının listesidir.

Basit Örnek

Soruda verilen örnekle, istisnanın uygulamada nereye atıldığını tam olarak belirleyebiliriz. Yığın izine bir göz atalım:

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)

Bu çok basit bir yığın izidir. "At ..." listesinin başından başlarsak, hatanızın nerede olduğunu söyleyebiliriz. Aradığımız, uygulamamızın bir parçası olan en üstteki yöntem çağrısıdır. Bu durumda:

at com.example.myproject.Book.getTitle(Book.java:16)

Bunu hata ayıklamak için, açıp Book.javaçizgiye bakabiliriz 16, yani:

15   public String getTitle() {
16      System.out.println(title.toString());
17      return title;
18   }

Bu, bir şeylerin (muhtemelen title) nullyukarıdaki kodda olduğunu gösterir.

İstisna zinciriyle örnek

Bazen uygulamalar bir İstisna yakalar ve başka bir İstisna nedeni olarak yeniden atar. Bu genellikle şöyle görünür:

34   public void getBookIds(int id) {
35      try {
36         book.getId(id);    // this method it throws a NullPointerException on line 22
37      } catch (NullPointerException e) {
38         throw new IllegalStateException("A book has a null property", e)
39      }
40   }

Bu size aşağıdaki gibi bir yığın izlemesi verebilir:

Exception in thread "main" java.lang.IllegalStateException: A book has a null property
        at com.example.myproject.Author.getBookIds(Author.java:38)
        at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Caused by: java.lang.NullPointerException
        at com.example.myproject.Book.getId(Book.java:22)
        at com.example.myproject.Author.getBookIds(Author.java:36)
        ... 1 more

Bu konuda farklı olan "Neden". Bazen istisnaların birden çok "Neden" bölümü olabilir. Bunlar için, genellikle yığın izindeki en düşük "Neden" bölümünden biri olacak "kök neden" i bulmak istersiniz. Bizim durumumuzda:

Caused by: java.lang.NullPointerException <-- root cause
        at com.example.myproject.Book.getId(Book.java:22) <-- important line

Yine, bu istisna ile biz çizgisinde bakmak isterdim 22arasında Book.javaneden olabilir ne olduğunu görmek için NullPointerExceptionburaya.

Kütüphane koduyla daha göz korkutucu örnek

Genellikle yığın izleri yukarıdaki iki örnekten çok daha karmaşıktır. İşte bir örnek (uzun bir örnek, ancak birkaç zincirleme istisna seviyesi gösterir):

javax.servlet.ServletException: Something bad happened
    at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:60)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.example.myproject.ExceptionHandlerFilter.doFilter(ExceptionHandlerFilter.java:28)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at com.example.myproject.OutputBufferFilter.doFilter(OutputBufferFilter.java:33)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:326)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
Caused by: com.example.myproject.MyProjectServletException
    at com.example.myproject.MyServlet.doPost(MyServlet.java:169)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
    at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:30)
    ... 27 more
Caused by: org.hibernate.exception.ConstraintViolationException: could not insert: [com.example.myproject.MyEntity]
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:64)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2329)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2822)
    at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:268)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:321)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
    at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
    at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:705)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:693)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:689)
    at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:344)
    at $Proxy19.save(Unknown Source)
    at com.example.myproject.MyEntityService.save(MyEntityService.java:59) <-- relevant call (see notes below)
    at com.example.myproject.MyServlet.doPost(MyServlet.java:164)
    ... 32 more
Caused by: java.sql.SQLException: Violation of unique constraint MY_ENTITY_UK_1: duplicate value(s) for column(s) MY_COLUMN in statement [...]
    at org.hsqldb.jdbc.Util.throwError(Unknown Source)
    at org.hsqldb.jdbc.jdbcPreparedStatement.executeUpdate(Unknown Source)
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
    at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:57)
    ... 54 more

Bu örnekte, çok daha fazlası var. En çok endişe duyduğumuz şey, com.example.myprojectpaketteki herhangi bir şey olabilecek kodumuzdan yöntemler aramaktır. İkinci örnekten (yukarıda), öncelikle kök nedenini araştırmak istiyoruz, yani:

Caused by: java.sql.SQLException

Ancak, altındaki tüm yöntem çağrıları kütüphane kodudur. Bu yüzden, üstündeki "Neden" e geçeceğiz ve kodumuzdan kaynaklanan ilk yöntem çağrısını arayacağız;

at com.example.myproject.MyEntityService.save(MyEntityService.java:59)

Önceki örneklerde olduğu gibi, MyEntityService.javaçevrimiçi olarak bakmalıyız 59, çünkü bu hatanın kaynağı burasıdır (SQLException hatayı bildirdiği için hata olan şey biraz açıktır, ancak hata ayıklama prosedürü peşinde olduğumuzdur).


3
@RHHruska - Çok iyi açıklanmış. +1. İstisna izini dize olarak alan ve yığın izlemesini analiz etmek için yararlı yöntemler sağlayan herhangi bir ayrıştırıcı biliyor musunuz? - getLastCausedBy () veya getCausedByForMyAppCode ("com.example.myproject") gibi
Andy Dufresne

1
@AndyDufresne - Hiç rastlamadım, ama yine de ben de bakmadım.
Rob Hruska

1
Önerilen iyileştirme: Exception in thread "main"ilk örneğinizde başlayan yığın izlemenin ilk satırını açıklayın . Bu çizginin, genellikle, sorunu teşhis etmeye yardımcı olabilecek bir değişkenin değeri gibi bir mesajın eşlik ettiğini açıklamak özellikle yararlı olacaktır. Kendimi bir düzenleme yapmaya çalıştım, ancak bu fikirleri cevabınızın mevcut yapısına uydurmaya çalışıyorum.
Code-Apprentice

5
Ayrıca java 1.7 eklenmiş "Suppressed:" - bu özel durum için "Caused::" ifadesini görüntülemeden önce bastırılan özel durum yığın izlerini listeler. Otomatik olarak kaynak- yapıyla dene : docs.oracle.com/javase/specs/jls/se8/html/… tarafından kullanılır ve kaynakların kapatılması sırasında atılan istisnalar içerir.
dhblah

'This.nullInstanceField' alanı boş olduğu için '' nullInstanceField alanı yazılamıyor 'gibi ayrıntılar sağlayarak özellikle NPE'lerin anlaşılabilirliğini daha da artırmayı amaçlayan bir JEP openjdk.java.net/jeps/8220715 vardır.
Mahatma_Fatal_Error

80

Ben bu cevabı (aktiviteye göre sıralandığında) sadece düz yanlış bir cevap değil bu yüzden gönderiyorum.

Stacktrace nedir?

Stacktrace çok yararlı bir hata ayıklama aracıdır. Yakalanmayan bir istisna atıldığında (veya yığın izinin elle oluşturulduğu zaman) çağrı yığınını (yani, o noktaya kadar çağrılan işlev yığınını) gösterir. Bu çok kullanışlıdır, çünkü size yalnızca hatanın nerede olduğunu göstermekle kalmaz, aynı zamanda programın kodun bu yerine nasıl geldiğini de gösterir. Bu bir sonraki soruya yönlendirir:

İstisna nedir?

İstisna, çalışma ortamının size bir hata oluştuğunu söylemek için kullandığı şeydir. Popüler örnekler NullPointerException, IndexOutOfBoundsException veya ArithmeticException'dır. Bunların her biri, mümkün olmayan bir şey yapmaya çalıştığınızda oluşur. Örneğin, bir Null nesnesinin başvurusunu kaldırmaya çalıştığınızda bir NullPointerException oluşturulur:

Object a = null;
a.toString();                 //this line throws a NullPointerException

Object[] b = new Object[5];
System.out.println(b[10]);    //this line throws an IndexOutOfBoundsException,
                              //because b is only 5 elements long
int ia = 5;
int ib = 0;
ia = ia/ib;                   //this line throws an  ArithmeticException with the 
                              //message "/ by 0", because you are trying to
                              //divide by 0, which is not possible.

Stacktraces / Exceptions ile nasıl başa çıkmalıyım?

İlk önce, İstisnaya neyin sebep olduğunu bulun. İstisnanın nedenini öğrenmek için istisnanın adını google olarak deneyin. Çoğu zaman yanlış koddan kaynaklanır. Yukarıdaki örneklerde, tüm istisnalar yanlış koddan kaynaklanmaktadır. NullPointerException örneği için bunun ao zaman asla boş olmadığından emin olabilirsiniz . Örneğin, aböyle bir çeki başlatabilir veya dahil edebilirsiniz:

if (a!=null) {
    a.toString();
}

Bu şekilde, rahatsız edici çizgi çalıştırılmaz a==null. Aynı durum diğer örnekler için de geçerlidir.

Bazen bir istisna olmadığından emin olamazsınız. Örneğin, programınızda bir ağ bağlantısı kullanıyorsanız, bilgisayarın Internet bağlantısını kaybetmesini durduramazsınız (örneğin kullanıcının bilgisayarın ağ bağlantısını kesmesini engelleyemezsiniz). Bu durumda ağ kitaplığı muhtemelen bir istisna atar. Şimdi istisnayı yakalamalı ve ele almalısınız . Bu, ağ bağlantısı olan örnekte, bağlantıyı yeniden açmaya çalışmanız veya kullanıcıyı veya bunun gibi bir şeyi bilgilendirmeniz gerektiği anlamına gelir. Ayrıca, catch'i her kullandığınızda, her zaman yalnızca yakalamak istediğiniz istisnayı yakalayın, geniş catch deyimlerini kullanmayın.catch (Exception e)tüm istisnaları yakalardı. Bu çok önemlidir, çünkü aksi takdirde yanlış istisnayı yakalayabilir ve yanlış şekilde tepki verebilirsiniz.

try {
    Socket x = new Socket("1.1.1.1", 6789);
    x.getInputStream().read()
} catch (IOException e) {
    System.err.println("Connection could not be established, please try again later!")
}

Neden kullanmamalıyım catch (Exception e)?

Neden tüm istisnaları yakalamamanız gerektiğini göstermek için küçük bir örnek kullanalım:

int mult(Integer a,Integer b) {
    try {
        int result = a/b
        return result;
    } catch (Exception e) {
        System.err.println("Error: Division by zero!");
        return 0;
    }
}

Ne bu kod yapmaya çalışıyor yakalamak için ArithmeticException0. tarafından olası bir bölünme neden olduğu Ama aynı zamanda olası bir yakalarsa NullPointerExceptioneğer atılır aya bvardır null. Yani, bir alabilirsiniz NullPointerExceptionama bir ArithmeticException olarak ele alacak ve muhtemelen yanlış bir şey yapacaksınız. En iyi durumda hala bir NullPointerException olduğunu özledim. Bunun gibi şeyler hata ayıklamayı çok daha zorlaştırır, bu yüzden bunu yapma.

TLDR

  1. İstisnanın nedenini anlayın ve düzeltin, böylece istisnayı hiç atmaz.
  2. 1. mümkün değilse, özel istisnayı yakalayın ve yönetin.

    • Asla sadece bir try / catch eklemeyin ve sonra istisnayı görmezden gelin! Yapma bunu!
    • Asla kullanmayın catch (Exception e), her zaman belirli İstisnaları yakalayın. Bu sizi çok fazla baş ağrısından kurtaracaktır.

1
hata maskelemeden kaçınmamız için güzel bir açıklama
Sudip Bhandari

2
Ben bu cevabı (aktivite göre sıralandığında) sadece düz yanlış değil bu yüzden gönderiyorum Bu muhtemelen şimdiye kadar değişti beri kim hakkında konuştuğunuz hakkında hiçbir fikrim yok. Ancak kabul edilen cevap kesinlikle daha interresting;)
AxelH

1
Demek istediğim şu ana kadar bildiğim kadarıyla silindi. Temel olarak "sadece bir dene {} catch (İstisna e) {} koy ve tüm hataları yoksay" dedi. Kabul edilen cevap cevabımdan çok daha eskidir, bu yüzden konuya biraz farklı bir bakış açısı sunmayı amaçlamıştım. Kimsenin sadece bir başkasının cevabını kopyalamasına veya başkalarının zaten iyi kapsadığı şeyleri kapsamasına yardımcı olduğunu düşünmüyorum.
Dakkaron

"İstisna yakalama" demek yanıltıcıdır, bu sadece bir kullanım örneğidir. Örneğiniz harika, ama iş parçacığı döngünüzün en üstünde nerede olduğunuza ne dersiniz? DAİMA orada istisna (ya da belki de Atılabilir) yakalamalı ve görünmez şekilde kaybolmaması için günlüğe kaydetmelisiniz (iş parçacığınızı / günlükçünüzü bunu yapmak için ayarlamadığınız sürece çalışmadan atılan özel durumlar genellikle doğru şekilde kaydedilmez).
Bill K

1
Bu özel durumu dahil etmedim, çünkü sadece çoklu iş parçacığı ile ilgili. Tek iş parçacığında geçirilen bir kural dışı durum, programı öldürür ve görünür biçimde günlüğe kaydedilir. Birisi istisnaları düzgün bir şekilde nasıl kullanacağını bilmiyorsa, genellikle çok iş parçacığının nasıl kullanılacağını da bilmez.
Dakkaron

21

Rob'un bahsettiklerine eklemek için. Uygulamanızda kesme noktaları ayarlamak, yığının adım adım işlenmesine olanak tanır. Bu, geliştiricinin, yöntemin beklenmedik bir şeyi tam olarak hangi noktada yaptığını görmek için hata ayıklayıcıyı kullanmasını sağlar.

Rob NullPointerExceptionyaygın bir şeyi göstermek için (NPE) kullandığından, bu sorunu aşağıdaki şekilde gidermeye yardımcı olabiliriz:

aşağıdaki gibi parametreleri alan bir yöntemimiz varsa: void (String firstName)

firstNameKodumuzda bir değer içeren değerlendirmek isteriz , bunu şöyle yaparız:if(firstName == null || firstName.equals("")) return;

Yukarıdakiler firstNamegüvenli olmayan bir parametre olarak kullanılmamızı engeller . Bu nedenle, işlemeden önce null kontroller yaparak kodumuzun düzgün çalışmasını sağlamaya yardımcı olabiliriz. Bir nesneyi yöntemlerle kullanan bir örneği genişletmek için buraya bakabiliriz:

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

Yukarıdaki null'ları kontrol etmek için uygun emirdir, temel nesne ile başlıyoruz, bu durumda köpek ve sonra işlemeden önce her şeyin geçerli olduğundan emin olmak için olasılıklar ağacında yürümeye başlıyoruz. Sipariş tersine çevrilirse, bir NPE potansiyel olarak atılabilir ve programımız çökebilir.


Kabul. Bu yaklaşım, bir açıklamada olan referans bulmak için kullanılabilir nullbir zaman NullPointerExceptionörneğin incelenmektedir.
Rob Hruska

16
Dize ile uğraşırken, eşittir yöntemi kullanmak istiyorsanız, karşılaştırmanın sol tarafındaki sabiti şu şekilde kullanmak daha iyi olduğunu düşünüyorum: Bunun yerine: if (firstName == null || firstName.equals ("" )) dönüş; Ben her zaman kullanıyorum: if ((""). Eşittir (firstName)) Bu Nullpointer istisnasını önler
Torres

15

Throwable ailesi tarafından sunulan bir yığın yığın özelliği daha var - yığın izleme bilgilerini değiştirme olanağı .

Standart davranış:

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();
    }
}

Yığın izleme:

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)

Manipüle yığın izi:

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();
    }
}

Yığın izleme:

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

2
Bu konuda nasıl hissettiğimi bilmiyorum ... iş parçacığının doğası ile, yeni geliştiricilere kendi yığın izlerini tanımlamamalarını tavsiye ederim.
PeonProgrammer

15

Adı anlamak için : Yığın izlemesi bir Özel Durumlar listesidir (veya "Yüzey Nedeni" nin bir listesini, en yüzey İstisnasından (örn. Hizmet Katmanı İstisnası) en derinine (örn. Veritabanı İstisnası) kadar söyleyebilirsiniz. Tıpkı 'yığın' olarak adlandırmamızın nedeni, yığının İlk Girdi Sonunda (FILO) olması gibi, en derin istisna başlangıçta gerçekleşti, daha sonra bir dizi istisna zinciri bir dizi sonuç üretti, yüzey İstisna son oldu biri zamanında oldu, ama biz ilk etapta görüyoruz.

Anahtar 1 : Burada anlaşılması gereken zor ve önemli bir şey şudur: en derin neden "kök neden" olmayabilir, çünkü bazı "kötü kod" yazarsanız, altında katmanından daha derin olan bir istisnaya neden olabilir. Örneğin, bozuk bir sql sorgusu, yalnızca yığının ortasında olabilecek sözdizimi hatası yerine bottem'de SQLServerException bağlantısının sıfırlanmasına neden olabilir.

-> Ortadaki işinizin kök nedenini bulun. resim açıklamasını buraya girin

Anahtar 2 : Bir başka zor ama önemli şey, her bir "Neden" bloğunun içinde, ilk satır en derin katmandı ve bu blok için ilk sırada yer aldı. Örneğin,

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, Bootstrap.java:14 tarafından çağrılan Auther.java:25 tarafından çağrıldı, bunun nedeni Book.java:16. Burada izleme yığınını kronolojik sırada sıralayan bir diyagram ekleyin. resim açıklamasını buraya girin


8

Sadece diğer örneklere eklemek için, işaretle görünen iç (iç içe) sınıflar vardır $. Örneğin:

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();
    }
}

Bu yığın izlemesine neden olur:

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)

5

Diğer gönderiler, yığın izlemenin ne olduğunu açıklar, ancak yine de çalışmak zor olabilir.

Bir yığın izleme almak ve istisna nedeni izlemek istiyorsanız, anlamada iyi bir başlangıç noktası kullanmaktır Java Yığın İzleme Konsolu içinde Eclipse . Başka bir IDE kullanırsanız benzer bir özellik olabilir, ancak bu cevap Eclipse ile ilgilidir.

İlk olarak, bir Eclipse projesinde tüm Java kaynaklarınızın erişilebilir olduğundan emin olun.

Daha sonra Java perspektifinde Konsol sekmesine tıklayın (genellikle altta). Konsol görünümü görünmüyorsa Pencere -> Görünümü Göster menü seçeneğine gidin ve Konsol'u seçin .

Ardından konsol penceresinde aşağıdaki düğmeyi tıklayın (sağda)

Konsollar düğmesi

ve ardından açılır listeden Java Stack Trace Console'u seçin.

Yığın izinizi konsola yapıştırın. Daha sonra kaynak kodunuza ve mevcut diğer kaynak kodlarına bir bağlantı listesi sağlar.

Gördüğünüz şey budur (Eclipse belgelerindeki resim):

Eclipse belgelerinden diyagram

Yapılan en son yöntem çağrısı , üst satır olan yığının üst kısmı olacaktır (mesaj metni hariç). Yığının aşağı inmesi zaman içinde geriye gider. İkinci satır, ilk satırı vb. Çağıran yöntemdir.

Açık kaynaklı yazılım kullanıyorsanız, incelemek istiyorsanız kaynakları indirip projenize eklemeniz gerekebilir. Kaynak kavanozlarını indirin, projenizde, açık kaynak modülünüzün (sınıf dosyalarına sahip olanı) kavanozunuzu bulmak için Referanslı Kitaplıklar klasörünü açın, ardından sağ tıklayın, Özellikler'i seçin ve kaynak kavanozunu ekleyin.

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.