Apa yang bisa menyebabkan a java.lang.StackOverflowError
? Hasil cetakan stack yang saya dapatkan tidak terlalu dalam sama sekali (hanya 5 metode).
87
Apa yang bisa menyebabkan a java.lang.StackOverflowError
? Hasil cetakan stack yang saya dapatkan tidak terlalu dalam sama sekali (hanya 5 metode).
Jawaban:
Periksa panggilan yang menyimpang untuk metode. Terutama disebabkan ketika ada panggilan rekursif untuk suatu metode. Contoh sederhananya adalah
public static void main(String... args) { Main main = new Main(); main.testMethod(1); } public void testMethod(int i) { testMethod(i); System.out.println(i); }
Di sini System.out.println (i); akan berulang kali didorong ke stack saat testMethod dipanggil.
sumber
Salah satu argumen (opsional) untuk JVM adalah ukuran tumpukan. Ini -Xss. Saya tidak tahu apa nilai defaultnya, tetapi jika jumlah total barang di tumpukan melebihi nilai itu, Anda akan mendapatkan kesalahan itu.
Umumnya, rekursi tak terbatas adalah penyebabnya, tetapi jika Anda melihatnya, pelacakan tumpukan Anda akan memiliki lebih dari 5 bingkai.
Coba tambahkan argumen -Xss (atau tingkatkan nilainya) untuk melihat apakah ini hilang.
sumber
Apa yang sebenarnya menyebabkan java.lang.StackOverflowError biasanya merupakan rekursi yang tidak disengaja. Bagi saya, sering kali saya bermaksud memanggil metode super untuk metode terlarang. Seperti dalam kasus ini:
public class Vehicle { public void accelerate(float acceleration, float maxVelocity) { // set the acceleration } } public class SpaceShip extends Vehicle { @Override public void accelerate(float acceleration, float maxVelocity) { // update the flux capacitor and call super.accelerate // oops meant to call super.accelerate(acceleration, maxVelocity); // but accidentally wrote this instead. A StackOverflow is in our future. this.accelerate(acceleration, maxVelocity); } }
Pertama, sangat berguna untuk mengetahui apa yang terjadi di balik layar saat kita memanggil suatu fungsi. Argumen dan alamat tempat metode dipanggil didorong pada tumpukan (lihat http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management ) sehingga metode yang dipanggil dapat mengakses argumen dan metode yang dipanggil selesai, eksekusi dapat dilanjutkan setelah panggilan. Tapi karena kita memanggil this.accelerate (acceleration, maxVelocity) secara rekursif (rekursi longgar saat metode memanggil dirinya sendiri. Untuk info lebih lanjut lihat http://en.wikipedia.org/wiki/Recursion_(computer_science)) kita berada dalam situasi yang dikenal sebagai rekursi tak terbatas dan kita terus menumpuk argumen dan alamat pengirim pada tumpukan panggilan. Karena tumpukan panggilan berukuran terbatas, kami akhirnya kehabisan ruang. Kehabisan ruang pada tumpukan panggilan dikenal sebagai luapan. Ini karena kami mencoba menggunakan lebih banyak ruang tumpukan daripada yang kami miliki dan data benar-benar meluap dari tumpukan. Dalam bahasa pemrograman Java, ini menghasilkan pengecualian runtime java.lang.StackOverflow dan akan segera menghentikan program.
Contoh di atas agak disederhanakan (meskipun itu terjadi pada saya lebih dari yang ingin saya akui.) Hal yang sama dapat terjadi secara lebih bulat tentang cara membuatnya sedikit lebih sulit untuk dilacak. Namun, secara umum, StackOverflow biasanya cukup mudah diatasi, setelah terjadi.
Secara teori, dimungkinkan juga untuk memiliki stack overflow tanpa rekursi, tetapi dalam praktiknya, ini tampaknya merupakan peristiwa yang cukup langka.
sumber
apa yang
java.lang.StackOverflowError
Kesalahan ditampilkan
java.lang.StackOverflowError
untuk menunjukkan bahwa tumpukan aplikasi telah habis, karena rekursi yang dalam, yaitu program / skrip Anda berulang terlalu dalam.Detail
Kelas
StackOverflowError
extendsVirtualMachineError
yang menunjukkan bahwa JVM telah atau telah kehabisan sumber daya dan tidak dapat beroperasi lebih lanjut. KelasVirtualMachineError
yang meluasError
digunakan untuk menunjukkan masalah serius yang tidak boleh ditangkap oleh aplikasi. Metode mungkin tidak mendeklarasikan kesalahan seperti itu dalamthrow
klausulnya karena kesalahan ini adalah kondisi abnormal yang tidak pernah diharapkan terjadi.Sebuah contoh
Minimal, Complete, and Verifiable Example
:package demo; public class StackOverflowErrorExample { public static void main(String[] args) { StackOverflowErrorExample.recursivePrint(1); } public static void recursivePrint(int num) { System.out.println("Number: " + num); if(num == 0) return; else recursivePrint(++num); } }
Output Konsol
Number: 1 Number: 2 . . . Number: 8645 Number: 8646 Number: 8647Exception in thread "main" java.lang.StackOverflowError at java.io.FileOutputStream.write(Unknown Source) at java.io.BufferedOutputStream.flushBuffer(Unknown Source) at java.io.BufferedOutputStream.flush(Unknown Source) at java.io.PrintStream.write(Unknown Source) at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source) at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source) at sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source) at java.io.OutputStreamWriter.flushBuffer(Unknown Source) at java.io.PrintStream.newLine(Unknown Source) at java.io.PrintStream.println(Unknown Source) at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:11) at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16) . . . at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)
Penjelasan
Saat panggilan fungsi dipanggil oleh Aplikasi Java, frame stack dialokasikan pada stack panggilan . The
stack frame
berisi parameter dari metode dipanggil, parameter lokal, dan alamat pengirim dari metode ini. Alamat pengirim menunjukkan titik eksekusi dari mana, eksekusi program harus dilanjutkan setelah metode yang dipanggil kembali. Jika tidak ada ruang untuk bingkai tumpukan baru, makaStackOverflowError
akan dilempar oleh Java Virtual Machine (JVM).Kasus paling umum yang mungkin dapat menghabiskan tumpukan aplikasi Java adalah rekursi. Dalam rekursi, metode memanggil dirinya sendiri selama eksekusinya.
Recursion
salah satu teknik pemrograman tujuan umum yang paling kuat, tetapi harus digunakan dengan hati-hati, agar halStackOverflowError
itu dihindari.Referensi
sumber
Saat panggilan fungsi dipanggil oleh aplikasi Java, frame stack dialokasikan pada stack panggilan. Bingkai tumpukan berisi parameter metode yang dipanggil, parameter lokalnya, dan alamat kembalian metode tersebut.
Alamat pengirim menunjukkan titik eksekusi dari mana, eksekusi program harus dilanjutkan setelah metode yang dipanggil kembali. Jika tidak ada ruang untuk bingkai tumpukan baru, StackOverflowError dilemparkan oleh Java Virtual Machine (JVM) .
Kasus paling umum yang mungkin dapat menghabiskan tumpukan aplikasi Java adalah rekursi.
Mohon dilihat
Bagaimana mengatasi StackOverflowError
sumber
Solusi untuk pengguna Hibernate saat mengurai data:
Saya mengalami kesalahan ini karena saya sedang mengurai daftar objek yang dipetakan di kedua sisi
@OneToMany
dan@ManyToOne
ke json menggunakan jackson yang menyebabkan pengulangan tak terbatas.Jika Anda berada dalam situasi yang sama, Anda dapat menyelesaikannya dengan menggunakan anotasi
@JsonManagedReference
dan@JsonBackReference
.Definisi dari API:
JsonManagedReference ( https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonManagedReference.html ):
JsonBackReference: ( https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonBackReference.html ):
Contoh:
Owner.java:
@JsonManagedReference @OneToMany(mappedBy = "owner", fetch = FetchType.EAGER) Set<Car> cars;
Car.java:
@JsonBackReference @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "owner_id") private Owner owner;
Solusi lain adalah menggunakan
@JsonIgnore
yang hanya akan menetapkan nol ke lapangan.sumber
Saya membuat program dengan hibernate, di mana saya membuat dua kelas POJO, keduanya dengan objek satu sama lain sebagai anggota data. Ketika dalam metode utama saya mencoba menyimpannya di database, saya juga mendapat kesalahan ini.
Hal ini terjadi karena kedua kelas saling merujuk, sehingga membuat perulangan yang menyebabkan kesalahan ini.
Jadi, periksa apakah ada jenis hubungan seperti itu dalam program Anda.
sumber
Pengecualian Stack Overflow dapat terjadi jika ukuran tumpukan benang terus bertambah hingga mencapai batas maksimum.
Menyesuaikan opsi Stack Sizes (Xss dan Xmso) ...
Saya sarankan Anda melihat tautan ini: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 Ada banyak kemungkinan penyebab StackOverflowError, seperti yang Anda lihat di tautan ....
sumber
Dalam kasus saya, saya memiliki dua aktivitas. Pada aktivitas kedua saya lupa menempatkan super pada metode onCreate.
super.onCreate(savedInstanceState);
sumber
StackOverflowError
, saya tidak berpikir itu menjawab pertanyaan. Saya pikir jawaban yang tepat harus mencantumkan cara lain untuk mendapatkan pengecualian ini daripada menggunakan terlalu banyak rekursi atau mengatakan bahwa pasti tidak ada cara lain untuk mendapatkan pengecualian seperti itu kecuali dengan melemparkannya secara manual.