Terkadang ketika saya menjalankan aplikasi saya itu memberi saya kesalahan yang terlihat seperti:
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)
Orang-orang menyebut ini sebagai "tumpukan jejak". Apa itu tumpukan jejak? Apa yang bisa saya katakan tentang kesalahan yang terjadi di program saya?
Tentang pertanyaan ini - cukup sering saya melihat pertanyaan datang di mana seorang programmer pemula "mendapatkan kesalahan", dan mereka hanya menempelkan jejak tumpukan mereka dan beberapa blok kode acak tanpa memahami apa jejak tumpukan itu atau bagaimana mereka dapat menggunakannya. Pertanyaan ini dimaksudkan sebagai referensi untuk pemrogram pemula yang mungkin perlu bantuan memahami nilai jejak tumpukan.
java
debugging
stack-trace
Rob Hruska
sumber
sumber
Jawaban:
Dalam istilah sederhana, jejak tumpukan adalah daftar metode panggilan bahwa aplikasi berada di tengah ketika Pengecualian dilemparkan.
Contoh sederhana
Dengan contoh yang diberikan dalam pertanyaan, kita dapat menentukan dengan tepat di mana pengecualian dilemparkan ke dalam aplikasi. Mari kita lihat jejak stack:
Ini adalah jejak tumpukan yang sangat sederhana. Jika kita mulai dari awal daftar "at ...", kita dapat mengetahui di mana kesalahan kita terjadi. Yang kami cari adalah pemanggilan metode teratas yang merupakan bagian dari aplikasi kami. Dalam hal ini, ini:
Untuk men-debug ini, kita dapat membuka
Book.java
dan melihat baris16
, yaitu:Ini akan menunjukkan bahwa sesuatu (mungkin
title
) adanull
dalam kode di atas.Contoh dengan rantai pengecualian
Terkadang aplikasi akan menangkap Pengecualian dan melemparkannya kembali sebagai penyebab Pengecualian lainnya. Ini biasanya terlihat seperti:
Ini mungkin memberi Anda jejak tumpukan yang terlihat seperti:
Yang berbeda dari yang satu ini adalah "Disebabkan oleh". Terkadang pengecualian memiliki beberapa bagian "Disebabkan oleh". Untuk ini, Anda biasanya ingin menemukan "akar penyebab", yang akan menjadi salah satu bagian "disebabkan oleh" terendah dalam jejak tumpukan. Dalam kasus kami, ini:
Sekali lagi, dengan pengecualian ini kita ingin melihat garis
22
dariBook.java
untuk melihat apa yang mungkin menyebabkanNullPointerException
sini.Contoh yang lebih menakutkan dengan kode perpustakaan
Biasanya jejak tumpukan jauh lebih kompleks daripada dua contoh di atas. Ini sebuah contoh (ini adalah contoh yang panjang, tetapi menunjukkan beberapa tingkat pengecualian berantai):
Dalam contoh ini, ada banyak lagi. Yang paling kami khawatirkan adalah mencari metode yang berasal dari kode kami , yang akan menjadi apa pun dalam
com.example.myproject
paket. Dari contoh kedua (di atas), pertama-tama kita ingin melihat ke bawah untuk penyebab root, yaitu:Namun, semua panggilan metode di bawah itu adalah kode perpustakaan. Jadi kita akan naik ke "Disebabkan oleh" di atasnya, dan mencari pemanggilan metode pertama yang berasal dari kode kita, yaitu:
Seperti pada contoh sebelumnya, kita harus melihat secara
MyEntityService.java
online59
, karena di situlah kesalahan ini berasal (kesalahan ini agak jelas apa yang salah, karena SQLException menyatakan kesalahan, tetapi prosedur debug adalah yang kita kejar).sumber
Exception in thread "main"
dalam contoh pertama Anda. Saya pikir akan sangat membantu untuk menjelaskan bahwa baris ini sering disertai dengan pesan, seperti nilai variabel, yang dapat membantu mendiagnosis masalah. Saya mencoba mengedit sendiri, tetapi saya berusaha menyesuaikan ide-ide ini dengan struktur jawaban Anda yang ada.Saya memposting jawaban ini sehingga jawaban teratas (saat diurutkan berdasarkan aktivitas) bukanlah salah yang jelas-jelas salah.
Apa itu Stacktrace?
Stacktrace adalah alat debugging yang sangat membantu. Ini menunjukkan tumpukan panggilan (artinya, tumpukan fungsi yang dipanggil ke titik itu) pada saat pengecualian tanpa pelemparan dilemparkan (atau saat stacktrace dihasilkan secara manual). Ini sangat berguna karena tidak hanya menunjukkan di mana kesalahan terjadi, tetapi juga bagaimana program berakhir di tempat kode itu. Ini mengarah ke pertanyaan berikutnya:
Apa itu Pengecualian?
Pengecualian adalah apa yang digunakan lingkungan runtime untuk memberi tahu Anda bahwa terjadi kesalahan. Contoh populer adalah NullPointerException, IndexOutOfBoundsException atau ArithmeticException. Masing-masing disebabkan ketika Anda mencoba melakukan sesuatu yang tidak mungkin. Sebagai contoh, NullPointerException akan dilemparkan ketika Anda mencoba melakukan dereferensi objek-Null:
Bagaimana saya harus berurusan dengan Stacktraces / Pengecualian?
Pada awalnya, cari tahu apa yang menyebabkan Pengecualian. Coba googleing nama pengecualian untuk mencari tahu, apa penyebab pengecualian itu. Sebagian besar waktu akan disebabkan oleh kode yang salah. Dalam contoh yang diberikan di atas, semua pengecualian disebabkan oleh kode yang salah. Jadi untuk contoh NullPointerException Anda dapat memastikan bahwa
a
tidak pernah nol pada waktu itu. Anda dapat, misalnya, menginisialisasia
atau memasukkan cek seperti ini:Dengan cara ini, garis menyinggung tidak dieksekusi jika
a==null
. Hal yang sama berlaku untuk contoh lainnya.Terkadang Anda tidak dapat memastikan bahwa Anda tidak mendapatkan pengecualian. Misalnya, jika Anda menggunakan koneksi jaringan dalam program Anda, Anda tidak dapat menghentikan komputer dari kehilangan koneksi internetnya (mis. Anda tidak dapat menghentikan pengguna untuk memutuskan koneksi jaringan komputer). Dalam hal ini perpustakaan jaringan mungkin akan melempar pengecualian. Sekarang Anda harus menangkap pengecualian dan menanganinya . Ini berarti, dalam contoh dengan koneksi jaringan, Anda harus mencoba untuk membuka kembali koneksi atau memberi tahu pengguna atau sesuatu seperti itu. Juga, setiap kali Anda menggunakan tangkapan, selalu hanya menangkap pengecualian yang ingin Anda tangkap, jangan gunakan pernyataan tangkapan luas seperti
catch (Exception e)
itu akan menangkap semua pengecualian. Ini sangat penting, karena jika tidak, Anda mungkin secara tidak sengaja menangkap pengecualian yang salah dan bereaksi dengan cara yang salah.Mengapa saya tidak menggunakannya
catch (Exception e)
?Mari kita gunakan contoh kecil untuk menunjukkan mengapa Anda tidak harus menangkap semua pengecualian:
Apa kode ini coba lakukan adalah untuk menangkap yang
ArithmeticException
disebabkan oleh kemungkinan pembagian dengan 0. Tetapi juga menangkap kemungkinanNullPointerException
yang dilemparkan jikaa
ataub
sedangnull
. Ini berarti, Anda mungkin mendapatkanNullPointerException
tetapi Anda akan memperlakukannya sebagai ArithmeticException dan mungkin melakukan hal yang salah. Dalam kasus terbaik Anda masih merindukan bahwa ada NullPointerException. Hal-hal seperti itu membuat proses debug jauh lebih sulit, jadi jangan lakukan itu.TLDR
Jika 1. tidak memungkinkan, tangkap pengecualian spesifik dan tangani.
catch (Exception e)
, selalu dapatkan Pengecualian tertentu. Itu akan menghemat banyak sakit kepala.sumber
Untuk menambah apa yang disebutkan Rob. Mengatur titik-titik istirahat pada aplikasi Anda memungkinkan untuk pemrosesan tumpukan secara bertahap. Ini memungkinkan pengembang untuk menggunakan debugger untuk melihat pada titik yang tepat metode ini melakukan sesuatu yang tidak terduga.
Karena Rob telah menggunakan
NullPointerException
(NPE) untuk menggambarkan sesuatu yang umum, kami dapat membantu menghapus masalah ini dengan cara berikut:jika kita memiliki metode yang mengambil parameter seperti:
void (String firstName)
Dalam kode kami, kami ingin mengevaluasi yang
firstName
berisi nilai, kami akan melakukan ini seperti ini:if(firstName == null || firstName.equals("")) return;
Hal di atas mencegah kita dari menggunakan
firstName
sebagai parameter yang tidak aman. Karenanya dengan melakukan pemeriksaan nol sebelum memproses kami dapat membantu memastikan bahwa kode kami akan berjalan dengan baik. Untuk memperluas contoh yang menggunakan objek dengan metode, kita dapat melihat di sini:if(dog == null || dog.firstName == null) return;
Di atas adalah urutan yang tepat untuk memeriksa nol, kita mulai dengan objek dasar, anjing dalam kasus ini, dan kemudian mulai berjalan di pohon kemungkinan untuk memastikan semuanya valid sebelum diproses. Jika pesanan dibatalkan, NPE berpotensi terlempar dan program kami akan macet.
sumber
null
ketika sebuahNullPointerException
sedang diperiksa, misalnya.Ada satu lagi fitur stacktrace yang ditawarkan oleh keluarga Throwable - kemungkinan untuk memanipulasi informasi jejak stack.
Perilaku standar:
Jejak tumpukan:
Jejak tumpukan yang dimanipulasi:
Jejak tumpukan:
sumber
Untuk memahami namanya : Jejak tumpukan adalah daftar Pengecualian (atau Anda dapat mengatakan daftar "Penyebab oleh"), dari Pengecualian yang paling permukaan (mis. Pengecualian Lapisan Layanan) ke yang paling dalam (mis. Pengecualian Basis Data). Sama seperti alasan kami menyebutnya 'tumpukan' adalah karena tumpukan adalah First in Last out (FILO), pengecualian terdalam terjadi di awal, kemudian rantai pengecualian menghasilkan serangkaian konsekuensi, permukaan Pengecualian adalah yang terakhir satu terjadi pada waktunya, tetapi kita melihatnya sejak awal.
Kunci 1 : Hal rumit dan penting yang perlu dipahami di sini adalah: penyebab terdalam mungkin bukan "penyebab utama", karena jika Anda menulis beberapa "kode buruk", ini dapat menyebabkan beberapa pengecualian di bawahnya yang lebih dalam dari lapisannya. Misalnya, kueri sql yang buruk dapat menyebabkan reset koneksi SQLServerException di bottem bukannya kesalahan syndax, yang mungkin hanya di tengah tumpukan.
-> Temukan akar penyebab di tengah adalah pekerjaan Anda.
Kunci 2 : Hal rumit tapi penting lainnya ada di dalam setiap blok "Penyebab", baris pertama adalah lapisan terdalam dan terjadi di tempat pertama untuk blok ini. Contohnya,
Book.java:16 dipanggil oleh Auther.java:25 yang disebut oleh Bootstrap.java:14, Book.java:16 adalah akar penyebabnya. Di sini melampirkan diagram mengurutkan jejak jejak dalam urutan kronologis.
sumber
Hanya untuk menambah contoh lain, ada kelas dalam (bersarang) yang muncul dengan
$
tanda. Sebagai contoh:Akan menghasilkan jejak tumpukan ini:
sumber
Posting lain menggambarkan apa itu stack trace, tetapi masih sulit untuk dikerjakan.
Jika Anda mendapatkan tumpukan jejak dan ingin melacak penyebab pengecualian, titik awal yang baik dalam memahami itu adalah menggunakan Java Stack Trace Console di Eclipse . Jika Anda menggunakan IDE lain mungkin ada fitur serupa, tetapi jawaban ini tentang Eclipse.
Pertama, pastikan bahwa Anda memiliki semua sumber Java Anda dapat diakses di proyek Eclipse.
Kemudian dalam perspektif Java , klik pada tab Konsol (biasanya di bagian bawah). Jika tampilan Konsol tidak terlihat, buka opsi menu Window -> Show View dan pilih Console .
Kemudian di jendela konsol, klik tombol berikut (di sebelah kanan)
dan kemudian pilih Java Stack Trace Console dari daftar drop-down.
Rekatkan jejak tumpukan Anda ke konsol. Ini kemudian akan memberikan daftar tautan ke kode sumber Anda dan kode sumber lainnya yang tersedia.
Ini yang mungkin Anda lihat (gambar dari dokumentasi Eclipse):
Panggilan metode terbaru yang dilakukan akan menjadi bagian atas tumpukan, yang merupakan baris teratas (tidak termasuk teks pesan). Turun tumpukan kembali ke waktu. Baris kedua adalah metode yang memanggil saluran pertama, dll.
Jika Anda menggunakan perangkat lunak sumber terbuka, Anda mungkin perlu mengunduh dan melampirkan proyek ke sumber Anda jika Anda ingin memeriksanya. Unduh toples sumber, di proyek Anda, buka folder Pustaka yang direferensikan untuk menemukan tabung Anda untuk modul sumber terbuka Anda (yang berisi file kelas) kemudian klik kanan, pilih Properties dan pasang toples sumber.
sumber